← 返回题目列表

Nginx 如何做到修改配置不中断服务(平滑重载)?

高频 中等 第 8 / 25 题 更新于 2026/07/28
Nginx平滑重载信号master-worker

简化版

Nginx 通过 nginx -s reload(本质是给 master 进程发 HUP 信号)实现平滑重载配置、不中断服务。原理:master 收到 reload 信号后,先用新配置启动一批新的 worker 进程,让新 worker 接收新请求;同时通知旧 worker「优雅退出」——不再接收新请求,但把手头正在处理的请求处理完,处理完后才退出。整个过程新旧 worker 短暂共存、平滑交接,正在进行的请求不会被打断,新请求由新配置处理,实现零停机更新配置。

详细版

平滑重载(reload)流程:

1. 执行 nginx -s reload(给 master 发 SIGHUP 信号)
2. master 校验新配置文件,语法有误则放弃、保持旧配置运行
3. master 用【新配置】启动【新的 worker 进程】
4. 新 worker 开始接收并处理【新请求】
5. master 向【旧 worker】发送信号,让它们「优雅关闭」:
   - 旧 worker 停止接收新请求
   - 但继续把【已经在处理的请求】处理完
6. 旧 worker 处理完存量请求后自行退出
7. 至此全部切换到新配置,服务全程未中断

常用信号 / 命令:

命令信号作用
nginx -s reloadHUP平滑重载配置
nginx -s reopenUSR1重新打开日志文件(日志切割用)
nginx -s quitQUIT优雅停止(处理完存量请求再退)
nginx -s stopTERM快速停止(立即终止)
nginx -t校验配置文件语法

完整版教学

一、为什么需要平滑重载

线上 Nginx 经常要改配置——加一个后端、改路由、调限流参数。如果每次改配置都要先停 Nginx、再启动,那么在停到启的这段时间里,服务是中断的,所有请求都失败。对高可用系统这不可接受。

Nginx 支持 平滑重载(graceful reload)改完配置执行 nginx -s reload,配置立即生效,且整个过程服务不中断、正在进行的请求不受影响。这依赖它的 master-worker 进程模型

二、依托 master-worker 模型

回顾 Nginx 的进程结构:一个 master + 多个 worker

  • master 不处理请求,负责管理:读配置、管理 worker、响应信号。
  • worker 真正处理请求。

平滑重载的关键就在于 master 能同时管理「新配置的 worker」和「旧配置的 worker」,让它们短暂共存、平滑交接。

三、reload 的完整流程

执行 nginx -s reload 时(本质是给 master 发送 SIGHUP 信号):

  1. master 校验新配置:先解析新配置文件,如果语法有错,master 直接放弃重载、继续用旧配置运行——所以错误配置不会搞垮服务(但保险起见应先 nginx -t 测试)。
  2. 启动新 worker:配置正确的话,master 用新配置 fork 出一批新的 worker 进程
  3. 新 worker 接管新请求:新 worker 启动后立即开始接收和处理新进来的请求(用新配置)。
  4. 通知旧 worker 优雅退出:master 向旧 worker 发信号,让它们进入「优雅关闭」状态:
    • 不再接收新请求(新请求都交给新 worker);
    • 继续把自己手头已经在处理的请求处理完——不粗暴掐断。
  5. 旧 worker 处理完存量请求后退出:等旧 worker 把它正在处理的连接都处理完毕,就自行退出。
  6. 完成切换:此时只剩新 worker,全部走新配置,整个过程没有任何请求被中断

关键在第 4、5 步:旧 worker 是「优雅退出」——先停止接新活、但做完手头的活再走,所以正在处理的请求(比如一个还没返回的接口调用、一个正在下载的文件)不会被打断。

四、优雅关闭 vs 快速关闭

Nginx 停止也有两种方式,体现同样的「优雅」思想:

  • nginx -s quit(优雅停止,QUIT 信号):worker 停止接收新请求,但处理完存量请求后再退出。适合线上正常停服,不丢请求。
  • nginx -s stop(快速停止,TERM 信号)立即终止所有 worker,不管有没有正在处理的请求。粗暴、会中断请求,适合紧急情况。

线上操作应优先用优雅的 quit/reload,避免用 stop 打断请求。

五、其他常用信号:日志切割

nginx -s reopen(USR1 信号)用于日志切割:Nginx 的访问日志会越写越大,需要定期切割(如按天分文件)。切割流程:先把当前日志文件重命名(mv access.log access.log.20260724),然后执行 nginx -s reopen——Nginx 会重新打开日志文件(按配置里的路径创建新的 access.log),之后的日志写入新文件。整个过程不中断服务、不丢日志。这通常配合定时任务(logrotate/crontab)自动完成。

六、常见误区与追问

考点正确口径
平滑重载master 读取新配置并启动新 worker
不中断原因旧 worker 继续处理已有连接后退出
关键命令nginx -t 检查配置,nginx -s reload 发送 HUP
nginx -t
nginx -s reload

master receives HUP
start new workers with new config
old workers stop accepting and drain existing connections

平滑重载不是没有进程变化,而是新旧 worker 交替,旧连接处理完再退出。

  • 误区:reload 会直接杀掉所有连接。 平滑 reload 下旧 worker 会停止接新连接并处理完已有连接。
  • 误区:改完配置直接 reload 就行。 应先 nginx -t 检查语法,避免配置错误导致新 worker 启不来。
  • 误区:reload 能修复所有运行时问题。 reload 主要加载配置,模块升级、二进制升级或资源泄漏可能需要其他流程。
  • 追问:master 和 worker 分工是什么? master 管理进程和信号,worker 处理实际连接。
  • 追问:长连接会影响 reload 吗? 旧 worker 可能因长连接迟迟不退出,需要配置超时和观察进程。
  • 追问:如何回滚错误配置? 保留旧配置,nginx -t 失败不 reload;若已生效则恢复旧配置再 reload。

七、加强记忆

Nginx 用 nginx -s reload(给 master 发 SIGHUP 信号) 实现平滑重载配置、零中断,依托 master-worker 模型。流程:master 先校验新配置(有错则放弃、保旧配置)→ 用新配置启动新 worker 接管新请求 → 通知旧 worker 优雅退出(停止接新请求、但把手头请求处理完再退)→ 旧 worker 处理完存量后退出,全程新旧 worker 短暂共存、正在进行的请求不被打断。相关信号:reload(HUP 重载)、reopen(USR1 重开日志用于切割)、quit(QUIT 优雅停止)、stop(TERM 快速停止),改配置前先 nginx -t 校验。核心:旧 worker 优雅退出(做完手头活再走)是不中断的关键