nginx reload时对http keepalive连接的处理
nginx各协议的reload行为
协议 | 行为 |
http keepalive | server fin |
http2 | server fin |
tcp | 保持shutdown不断 |
udp | 保持shutdown不断 |
grpc |
基于HTTP2与其保持一致,但是没实测 |
现象
nginx 在reload时,会对http keepalive的连接进行close操作。
抓包可以看见client收到了一个fin报文。
nginx 的worker也不会长时间留着shutdown状态,而是立刻退出。
4层的tcp监听上的连接,会使worker一直保留在shutdown状态。直到连接断开后,进程退出。
代码分析
一
见函数:ngx_worker_process_cycle,
所有idle的连接,会调用一次read的handler,然后将连接标记为close,最后在处理流程里根据这个标记,调用ngx_http_close_connection。关闭连接。
二
http keepalive过程
keepalive的连接会在每个request处理完的时候ngx_http_finalize_request调用连接关闭ngx_http_finalize_connection
在这个函数里,如果连接设了keepalive,就会进入 ngx_http_set_keepalive 函数
上述调用ngx_http_set_keepalive 函数的过程干三个事:
1 rev->handler = ngx_http_keepalive_handler;
2 c->idle = 1;
3 在2936行直接返回,跳过后面的connection close操作,所以连接还开着。
当 nginx reload的时候,2930或2931导致 ngx_http_set_keepalive 不会被调用,所以连接被关闭了,
抓包就看见了一个nginx到client的fin报文。
ngx_http_keepalive_handler
idle=1代表进程现在处于等待数据包读入状态。
ngx_http_keepalive_handler函数是数据包后的第一个handler,它的主要功能类似于 ngx_http_wait_request_handler 函数,
0 如果close=1,直接关闭连接。
1 设置idle = 0 (重新变成idle)
2 设置新的handler = ngx_http_process_request_line
request处理完成后,流程会重新走进ngx_http_finalize_request,最终判断是否进入ngx_http_set_keepalive
A 如果设置了ngx_exiting或者keepalive设置为0,将不会进入ngx_http_set_keepalive,直接将连接关闭。
B 否则再次进入ngx_http_set_keepalive 重新将idle设置为1,等待下一个请求的到来。
三
最后在函数ngx_worker_process_cycle,里。所有连接都关闭了,于是进程退出。
四
另外有个配置叫 worker_shutdown_timeout
https://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout
就是到时间之后,不管什么连接(包括tcp)全部断开进程退出,实现如下:将所有连接全部标记为close,然后再handler流程里close。
五
connection close的时候,会删掉read write timer,所有(三)里边的exit逻辑分支,再所有连接都断开了以后,就使进程退出了。
六
https://hg.nginx.org/nginx/rev/96ae8e57b3dd
这个是官方nginx的改动。主要是在nginx退出的时候,给keepalive的client回response时,带一个Connection:close。
基于(二)的代码分析,reload或exit发生时:
当connection处于idle时,nginx会直接将socket close掉。
然后client再发下一个response过来时,nginx的os回一个reset,client才知道失败了。(A)
当connection处于非idle(request处理过程中),且response还没发回时,会把response的Connection:keepalive改成Connection:close,紧接着socket close。
client的http层就会知道连接需要断开了。(B)
然后,进程退出。
另外,这个回复close的行为也就是情况(B),与 “keepalive_timeout到期,keepalive_requests满” 时的行为保持一致。
参考
https://github.com/alibaba/tengine/issues/1074
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具