Nginx 优雅退出依赖 Master 通过信号触发并经 channel socket 向 Worker 发送 QUIT 指令,Worker 停止 accept 新连接但处理完已有请求后退出,Master 待全部 Worker 退出后自身终止。

Nginx 的 Master 进程并不靠信号量,而是通过信号 + 进程间指令通道协调 Worker 优雅退出。整个过程是主从明确、单向驱动的协作机制,核心在于“不中断已建立连接,只拒新不杀旧”。
Master 收到退出信号后启动协调流程
当执行 nginx -s quit 或 kill -QUIT $(cat nginx.pid) 时,Master 进程捕获 SIGQUIT(或等效的 SIGTERM),随即开始以下动作:
- 关闭所有监听套接字(
ngx_close_listening_sockets()),使系统不再将新连接派发给任何 Worker - 通过预建的 channel socket 向每个 Worker 进程发送 QUIT 指令(不是系统信号,而是自定义协议消息)
- 将对应 Worker 在
ngx_processes[]数组中的exiting标志置为 1,并等待其主动退出 - 进入轮询状态:一旦收到 SIGCHLD(子进程终止通知),就调用
waitpid()确认退出,并把该 Worker 的exited标志设为 1
Worker 响应指令并自主完成清理
Worker 不响应系统信号本身,而是持续轮询 channel socket 中来自主进程的指令:
- 收到 QUIT 指令后,设置内部标志
ngx_exiting = 1 - 立即停止 accept 新连接,但保持所有已建立连接活跃(包括 keepalive、长轮询、上传中请求)
- 继续处理事件循环:完成剩余读写、定时器、upstream 响应、日志刷盘等任务
- 若配置了
worker_shutdown_timeout,超时后会强制关闭未完成连接;否则一直等到所有连接自然关闭或空闲超时 - 最后调用
ngx_worker_process_exit(),释放内存、关闭非监听 socket、退出进程
Master 完成收尾并自身退出
当 Master 观察到 ngx_processes[] 中所有 Worker 的 exited == 1,即确认全部 Worker 已退出:
- 清理自身资源:关闭 channel socket、释放 cycle、销毁共享内存(如有)
- 删除
nginx.pid文件 - 主进程终止
若某个 Worker 长时间未退出(如卡在阻塞 I/O 或后端无响应),Master 默认不会无限等待——可通过 worker_shutdown_timeout 控制 Worker 超时行为,但 Master 自身无硬性超时;此时需人工介入检查 error.log 中 “exiting” 日志及连接状态。
systemd 环境下需对齐配置
使用 systemctl stop nginx 时,能否走上述优雅路径,取决于服务单元文件是否正确配置:
-
KillMode=process:确保 systemd 只杀主进程,不波及 Worker(避免误发 SIGKILL) -
ExecStop=/usr/bin/nginx -s quit:显式调用原生 quit 流程,替代默认 kill -
TimeoutStopSec=30:为长连接留出足够缓冲时间,防止 fallback 到强制终止
绕过 ExecStop(如直接 systemctl kill nginx)会跳过整套协调逻辑,导致非优雅退出。


















