Nginx 进程和信号
进程结构
一般来说 Nginx 有一个父进程 Master,和一个或多个子进程。
子进程分两类,一种是 Worker 进程,另一种是 Cache 相关的进程。
Cache 在多个 Worker 间共享使用。同时被进程 Cache manager 和 Cache loader 使用。Cache loader 做缓存的载入,Cache manager 做缓存的管理。这些进程间的通讯都是使用共享内存来解决的。
为什么不用多线程?因为线程之间是共享地址空间的,当某一个第三方模块引发了地址空间的段错误时,地址越界出现时,会导致整个进程挂掉。
Nginx 希望每个 Worker 进程从头到尾占有一个 CPU,所以往往不止要把 Worker 进程的数量配置与服务器的 CPU 核数一致以外,还需要把每一个 Worker 进程与某一个 CPU 核绑定在一起。这样可以更好的使用每个 CPU 核上面的 CPU 缓存,提高缓存的命中率。
不仅仅是缓存的原因,一个进程从头到尾占有一个 CPU,减少 CPU 上下文切换的次数和耗时,让 CPU 更多的时间用在运行进程上。
Master 进程
监控 Worker 进程,接受信号
- CHLD,子进程终止的时候会向父进程发送 CHLD。Master 进程通过这个信号维持 Worker 进程的数量。
管理 Worker 进程,发送信号
- TERM/INT,立刻停止进程。
- QUIT,优雅的退出,等请求处理完才退出,用户无感知。
- HUP,重载配置文件。
- USR1,重新打开日志文件,做日志文件的切割。
下面 2 个信号,Nginx 命令行中没有对应的操作,只能通过 kill 直接向 Master 进程发送
- USR2,热升级第一阶段,启动新进程。旧的 Nginx 主进程 Master 将会把自己的进程文件改名为 .oldbin,然后执行新版 Nginx。此时新旧 Nginx 会同时运行,共同处理请求。
- WINCH,热升级第二阶段,停止老进程。逐步停止旧版 Nginx 的 Worker 进程就都会随着任务执行完毕而退出,新版的 Nginx 的 Worker 进程会逐渐取代旧版 Worker 进程。
Worker 进程
和上面对应,接受信号
Nginx 命令行
启动 Nginx 以后,Nginx 会把 Master 进程的 pid 记录到一个文件中,一般是 Nginx 安装目录下 logs/nginx.pid。
我们平时使用的命令行其实就是对这个 pid 发送对应的信号。
- reload: HUP
- reopen: USR1
- stop: TERM
- quit: QUIT
reload 流程
- 向 Master 进程发送 HUP 信号(reload 命令)
- Master 进程校验配置语法是否正确
- Master 进程更新监听端口(比如新配置增加了监听 443 端口)
- Master 进程用新配置启动新的 Worker 子进程
- Master 进程向老 Worker 子进程发送 QUIT 信号
- 老 Worker 子进程关闭监听句柄,处理完当前连接后结束进程
在 1.11.11 的版本中,增加了 worker_shutdown_timeout 参数来设置优雅退出 Worker 进程的超时时间。
热升级流程
- 将旧 Nginx 文件换成新 Nginx 文件(注意备份)
- 向 Master 进程发送 USR2 信号
- Master 进程修改 pid 文件名,加后缀 .oldbin
- Master 进程用新 Nginx 文件启动新 Master 进程
- 向老 Master 进程发送 WINCH 信号,老 Master 进程会优雅关闭老 Worker 进程
- 此时老 Master 进程依然存活,如果出现问题需要回滚。向老 Master 进程发送 HUP,然后向新 Master 发送 QUIT 即可。(注意恢复备份文件)
- 正常升级后,通过 kill -QUIT 信号关闭老 Master 进程
新老 Master 进程,同时存在,那么是怎么同时监听端口的?
新老 Master 进程是父子进程,所以可以同时监听。
优雅关闭 Worker 进程
优雅关闭是指 HTTP 请求,如果代理的是 WebSocket、TCP、UDP,这时候 Nginx 是无法进行优雅关闭的。
- 设置定时器(这个功能默认不开启,配置文件有设置 worker_shutdown_timeout 才会生效)
- 关闭监听句柄
- 关闭空闲连接
- 在循环中等待全部连接关闭(如果设置了 worker_shutdown_timeout,超时后会强制关闭全部连接)
- 退出进程
更多信息可以参考官方文档 Starting, Stopping, and Restarting NGINX
原文转自博客 Nginx 进程和信号