nginx平滑重载时长连接不中断,旧worker继续处理已建立的keepalive或websocket连接直至自然关闭,新worker仅处理新建连接;关键依赖keepalive_timeout和worker_shutdown_timeout配置。

在 Nginx 平滑重载(nginx -s reload)过程中,客户端长连接(如 HTTP/1.1 keepalive 或 WebSocket)能否持续不中断,取决于新旧 worker 进程的协作机制和连接迁移策略。直接观察“瞬间”状态较难,但可通过组合方式可靠验证其行为。
理解平滑重载时长连接的实际处理逻辑
Nginx 的 reload 不会主动关闭已有连接。旧 worker 进程继续处理已建立的长连接,直到这些连接自然关闭(超时、客户端断开或请求完成),同时不再接受新连接;新 worker 进程立即开始监听并处理新建连接。因此,**长连接本身不会被 kill,但后续请求是否走新进程,取决于连接是否复用及内核 socket 重用机制**。
关键点:
- keepalive 连接在 reload 后仍由原 worker 维持,只要未超时(
keepalive_timeout)且客户端未主动关闭; - 客户端若在 reload 后发起新请求并复用该连接,请求仍进入旧 worker;
- 只有当旧 worker 处理完所有现存连接并退出(
worker_shutdown_timeout限制下),reload 才真正完成。
用 curl + 抓包验证连接是否中断
启动一个带 keepalive 的长连接请求,同时 reload,并观察底层行为:
- 终端 A:运行
curl -v --http1.1 -H "Connection: keep-alive" http://localhost:80/ --output /dev/null,保持连接空闲(注意加--http1.1避免 HTTP/2 自动升级干扰); - 终端 B:执行
nginx -s reload; - 终端 C:用
tcpdump -i lo port 80 and host 127.0.0.1抓包,重点观察 FIN/RST 是否出现 —— 若 reload 后无 FIN 包,说明连接未断; - 稍等几秒后,在终端 A 再发一次请求(如 Ctrl+C 后重跑 curl),看是否仍能收到响应 —— 成功即表明复用有效。
通过 Nginx 状态指标交叉确认
启用 stub_status 模块(需编译时含 --with-http_stub_status_module),配置如下:
location /nginx_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
reload 前后分别请求 curl http://localhost/nginx_status,关注:
– Active connections 数值是否连续不归零(说明连接未被强制释放);
– Reading/Writing/Waiting 中 Waiting 数是否稳定存在(keepalive 空闲连接体现为 Waiting);
– 对比两次输出中 Accepts 和 Handled 的差值,若 Handling 数未跳变,间接反映连接延续性。
模拟真实长连接场景(如 WebSocket)
使用简单 WebSocket 客户端(如 wscat)建立连接:
- 启动:
wscat -c ws://localhost/ws(确保 Nginx 已正确代理 WebSocket,含Upgrade和Connection头透传); - 保持连接打开,发送一条消息确认通路;
- 执行 reload;
- 再发一条消息 —— 若服务端仍能接收并响应,说明 WebSocket 连接全程由同一 worker 持有,未因 reload 断连。
注意:需确认 Nginx 配置中已设置 proxy_http_version 1.1;、proxy_set_header Upgrade $http_upgrade;、proxy_set_header Connection "upgrade";,否则 upgrade 请求会被拒绝,无法建立长连接。











