upstream请求结束分三种情况:
read()、write()过程中出现NGX_ERROR/NGX_ABORT,表示请求过程中发生异常,设置p->upstream_error = 1;read()函数时后端关闭socket,后端系统发送FIN分节到nginx,接收到该信号则设置rev->ready = 0和p->upstream_eof = 1;正常情况下,upstream接收Header时会记录content-length,然后接收body时减小p->length的值,当所有body接收完时p->length=0,并设置p->upstream_done = 1;分析ngx_http_upstream_finalize_request():
清除cleanup指针,因为在upstream的前面阶段:create、init、发送请求、接收Headers时出现异常则会调用ngx_http_finalize_request(),并执行cleanup()的调用。所以这里首先要清除cleanup指针;u->finalize_request(),实际调用ngx_http_proxy_finalize_request,没有任何操作;u->peer.free(),实际调用’ngx_http_upstream_keepalive_close_handler()’进行peer的“关闭”操作;如果peer->connection不为空,则关闭connection,原因是上一步有可能是keepalive里把connection放到cache里后置为空,所以不用关闭connection;ngx_http_send_special(),设置一个带有last标志的特殊buffer,告知数据发送环节需要将之前缓存而没有发送的buffer chain,发送出去;ngx_http_finalize_request(),结束请求 如果还没数据没发送完c->buffered不为0,则设置write句柄为ngx_http_write,表示要继续发送数据,在函数ngx_http_write中ngx_htt_finalize_request()是最后执行,形成递归;若数据发送完了,则直接干到这一行r->done = 1,标记结束,并把client的write句柄关闭ngx_http_post_action(),若无后续操作,则无实际执行如果socket关闭了,会发送FIN分节,标记c->read->eof,执行ngx_http_close_request()关闭socket,????ngx_http_finalize_connection(),关闭链接 检查请求的引用计数器,不等于1说明还有多个动作在操作着请求???(请求创建时ngx_http_create_request()该值赋为1);引用计数器为1时,检查keepalive是否超时,接着结束keepalive请求返回;调用ngx_http_set_lingering_close(),默认lingering超时是5s 设置ngx_http_lingering_close_handler()读事件,意思客户端在lingering_timeout时间内没有进行任何操作,那么就会关闭与客户端的连接,如果有操作,也有总时间lingering_time超时,然后调用ngx_http_close_request()ngx_shutdown_socket(fd, NGX_WRITE_SHUTDOWN)关闭socket写端;调用ngx_http_lingering_close_handler(),进一步会ngx_http_free_request()打印请求日志、释放request,ngx_http_close_connection()中释放connection,并ngx_close_socket(fd)回收描述符。lingering机制详见nginx lingering_close,进一步也可以了解与之相关的case:nginx的延迟关闭。启用nginx到upstream的keepalive,需要设置proxy http\1.1和覆盖connection为空(nginx默认会置为close)。