讲讲Nginx 信号控制机制,常用的管理信号(如 HUP、QUIT、USR1、USR2)各有什么作用?
Nginx 的信号控制机制是其实现高性能和高可用性(如热部署、平滑重启)的核心机制之一。
要理解 Nginx 的信号控制,首先需要了解 Nginx 的进程模型:Master-Worker 模型。
- Master 进程:充当“大管家”,通常以 root 权限运行,负责读取和解析配置文件、管理 Worker 进程(启动、停止、重启)、接收外部信号。
- Worker 进程:充当“打工人”,通常以非特权用户运行,负责实际处理客户端的网络请求。
信号控制机制的本质是:管理员通过向 Master 进程发送特定的系统信号(Signal),Master 进程收到信号后,再通过内部进程间通信(IPC)机制,指挥 Worker 进程执行相应的操作,从而实现对 Nginx 服务的平滑管理。
下面详细讲解常用的管理信号及其作用:
1. SIGHUP (HUP) —— 平滑重载配置 (Reload)
- 作用:在不中断现有服务的情况下,重新加载配置文件。
- 等价命令:
nginx -s reload - 底层执行流程:
- Master 进程收到
HUP信号。 - Master 进程重新读取并校验配置文件。如果配置语法错误,Master 会拒绝并继续使用旧配置,服务不受影响。
- 如果配置正确,Master 进程会根据新配置启动全新的 Worker 进程。
- Master 进程向旧的 Worker 进程发送平滑关闭信号。
- 旧 Worker 进程停止接收新连接,等当前处理的请求结束后,旧 Worker 进程退出。
- Master 进程收到
- 使用场景:修改了
nginx.conf后,使新配置生效,且不影响正在访问网站的用户。
2. SIGQUIT (QUIT) —— 优雅/平滑关闭 (Graceful Shutdown)
- 作用:优雅地停止 Nginx 服务。
- 等价命令:
nginx -s quit - 底层执行流程:
- Master 进程收到
QUIT信号。 - Master 进程通知所有 Worker 进程停止工作。
- Worker 进程立即关闭监听套接字(停止接收新的请求)。
- Worker 进程继续处理已经建立连接的当前请求,直到所有请求处理完毕。
- Worker 进程退出。
- 所有 Worker 退出后,Master 进程退出。
- Master 进程收到
- 使用场景:计划内停机维护。与
SIGTERM/SIGINT(快速停止,等价于nginx -s stop)不同,QUIT保证了不会生硬地切断用户的当前请求。
3. SIGUSR1 (USR1) —— 重新打开日志文件 (Reopen Logs)
- 作用:重新打开日志文件,主要用于日志切割(Log Rotation)。
- 等价命令:
nginx -s reopen - 底层执行流程:
- 用户在操作系统层面将当前的
access.log重命名(例如mv access.log access.log.20231025)。此时 Nginx 依然会向重命名后的旧文件中写入日志(因为 Linux 按文件描述符 fd 写入,而不是文件名)。 - 向 Master 进程发送
USR1信号。 - Master 进程重新打开配置文件中指定的日志文件(从而创建了一个新的
access.log)。 - Master 进程通知 Worker 进程也重新打开日志文件。
- Worker 进程开始向新的日志文件写入数据。
- 用户在操作系统层面将当前的
- 使用场景:配合 Linux 的
logrotate工具,实现 Nginx 日志的按天/按大小自动切割,防止单个日志文件过大。
4. SIGUSR2 (USR2) —— 平滑升级可执行程序 (Hot Upgrade)
- 作用:在不中断服务的情况下,升级 Nginx 的二进制文件(例如从 1.20 升级到 1.22,或者添加了新的第三方模块)。
- 底层执行流程(这是 Nginx 最惊艳的特性之一):
- 用新的 Nginx 二进制文件替换旧的二进制文件。
- 向旧的 Master 进程发送
USR2信号。 - 旧 Master 进程会将自己的 PID 文件(如
nginx.pid)重命名为nginx.pid.oldbin。 - 旧 Master 进程使用新的 Nginx 二进制文件启动一个新的 Master 进程(此时新旧两个 Master 进程共存)。
- 新 Master 进程启动新的 Worker 进程。
- 此时,新旧 Worker 进程都在接收和处理请求。
- 向旧 Master 进程发送
WINCH信号(见下文),旧 Worker 进程平滑退出,所有流量转移到新 Worker 上。 - 验证新版本运行正常后,向旧 Master 发送
QUIT信号,旧 Master 退出,升级完成。
- 使用场景:生产环境对 Nginx 进行版本升级或打补丁,要求真正意义上的“零停机时间(Zero Downtime)”。
5. 其他补充信号
除了上述四个,还有几个辅助信号:
SIGWINCH(WINCH):平滑关闭所有 Worker 进程。通常配合USR2在平滑升级 Nginx 版本时使用。它只关闭 Worker,不关闭 Master。SIGTERM或SIGINT(TERM/INT):快速停止(等价于nginx -s stop)。Master 收到后,直接强制杀掉 Worker 进程,不管它们是否正在处理请求。
如何向 Nginx 发送信号?
在 Linux 系统中,通常使用 kill 命令结合 Nginx 的 PID(进程号)来发送信号。Nginx 的 PID 通常保存在 /var/run/nginx.pid 或者 /usr/local/nginx/logs/nginx.pid 中。
方法一:直接使用系统信号 (底层做法)
bash
# 获取 Master 进程 PID
PID=$(cat /var/run/nginx.pid)
# 发送信号
kill -HUP $PID # 平滑重载配置
kill -QUIT $PID # 平滑停止
kill -USR1 $PID # 切割日志
kill -USR2 $PID # 平滑升级
方法二:使用 Nginx 命令行参数 (日常推荐)
Nginx 封装了常见的信号,可以直接使用 -s (signal) 参数,Nginx 内部会自动帮你找到 PID 并发送对应的信号:
bash
nginx -s reload # 对应 SIGHUP
nginx -s quit # 对应 SIGQUIT
nginx -s stop # 对应 SIGTERM
nginx -s reopen # 对应 SIGUSR1
(注:USR2 平滑升级流程较复杂,没有对应的 -s 快捷命令,必须手动使用 kill 发送信号。)
总结对照表
| 信号 (Signal) | Nginx 快捷命令 | 核心作用 | 适用场景 |
|---|---|---|---|
| HUP | nginx -s reload |
平滑重载配置文件 | 修改 nginx.conf 后使之生效 |
| QUIT | nginx -s quit |
优雅停止服务 | 计划内停机,保护当前用户的请求不中断 |
| TERM / INT | nginx -s stop |
强制快速停止服务 | 紧急停机,不管请求是否完成 |
| USR1 | nginx -s reopen |
重新打开日志文件 | 日志定时切割 (log rotation) |
| USR2 | 无 | 准备平滑升级二进制文件 | Nginx 跨版本升级或热部署,零宕机时间 |
| WINCH | 无 | 平滑关闭 Worker 进程 | 配合 USR2 升级时,让旧 Worker 退场 |