nginx 通过反向代理转发请求给 node.js 实现零中断升级,需协同配置 nginx 热加载(启用 worker_shutdown_timeout、合理设置超时)、node.js 优雅退出(监听 sigterm 并关闭服务器),并端到端验证连接平滑过渡与请求完整性。

Nginx 本身不直接运行 Node.js,而是作为反向代理将请求转发给后端的 Node.js 服务(如用 pm2、systemd 或 node 直接启动的进程)。所以“Nginx 中 Node.js 部署”的零中断升级,本质是 Nginx 配置热加载 + Node.js 服务平滑重启 + 两者协同超时控制 的组合问题。只要三者配合得当,完全可以做到用户无感知。
Nginx 层:reload 必须带连接保持能力
Nginx 向 Node.js 转发请求时,自身不能成为中断源。关键不是“能不能 reload”,而是“reload 后旧连接是否被粗暴切断”。
必须启用
worker_shutdown_timeout:在http{}或main{}块中添加
worker_shutdown_timeout 30s;
它让旧 worker 在收到QUIT(由 reload 触发)后,继续处理已建立的长连接(HTTPS keep-alive、WebSocket、HTTP/2 stream),最多等 30 秒才退出。-
同步调优关联超时,避免时间窗口错配:
-
keepalive_timeout 65s;(略大于worker_shutdown_timeout,防止 reload 前连接被主动关闭) -
proxy_read_timeout 45s;和proxy_send_timeout 45s;(必须 ≥worker_shutdown_timeout,否则 Node.js 还没返回,Nginx 就断开了) -
proxy_http_version 1.1;与proxy_set_header Connection '';(启用 HTTP/1.1 keep-alive,禁用 Connection: close)
-
reload 前务必
nginx -t检查语法,失败会导致主进程拒绝加载新配置,但旧 worker 继续运行——看似没中断,实则配置未生效。
Node.js 层:必须支持优雅退出
Nginx 只负责把请求转过去,真正处理业务的是 Node.js 进程。如果它收到 SIGTERM 立即退出,正在响应的请求就会被截断。
-
使用进程管理器(推荐
pm2)并开启 graceful shutdown:pm2 start app.js --name myapp --watch \ --kill-timeout 5000 \ --shutdown-with-message
启动时加
--shutdown-with-message,并在代码中监听message事件,收到'shutdown'后停止接受新连接、等待已有请求完成再process.exit()。 -
手动管理时,在 Node.js 中写标准优雅退出逻辑:
const server = http.createServer(handler); server.listen(3000); process.on('SIGTERM', () => { console.log('SIGTERM received, closing server...'); server.close(() => { console.log('Server closed'); process.exit(0); }); // 可选:30秒强制退出兜底 setTimeout(() => process.exit(1), 30000); }); 确保
pm2 reload myapp或systemctl reload myapp.service发送的是SIGTERM(不是SIGKILL),且 Node.js 进程能捕获。
协同验证:确认整条链路不丢请求
单点验证不够,要测端到端行为:
reload Nginx 后,执行:
ss -tnp | grep :443 | grep ESTAB | wc -l
观察 HTTPS 连接数是否平滑过渡(不应归零或剧烈抖动)。对 Node.js 接口发起持续长轮询或 WebSocket 连接,reload 期间检查是否出现
1006(连接异常关闭)或ECONNRESET。抓包看 reload 时间点附近是否有 RST 包;同时检查 Nginx error log 是否有
recv() failed或upstream prematurely closed connection。Node.js 日志中确认每个请求都完整记录了
req → res.end(),无中途process.exit()导致的截断。
不复杂但容易忽略











