Nginx Nginx 进程和信号

tuliang · 2018年12月02日 · 最后由 lilijreey 回复于 2018年12月03日 · 880 次阅读
本帖已被设为精华帖!

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 进程

和上面对应,接受信号

  • TERM/INT
  • QUIT
  • USR1
  • WINCH

Nginx 命令行

启动 Nginx 以后,Nginx 会把 Master 进程的 pid 记录到一个文件中,一般是 Nginx 安装目录下 logs/nginx.pid。

我们平时使用的命令行其实就是对这个 pid 发送对应的信号。

  • reload: HUP
  • reopen: USR1
  • stop: TERM
  • quit: QUIT

reload 流程

  1. 向 Master 进程发送 HUP 信号(reload 命令)
  2. Master 进程校验配置语法是否正确
  3. Master 进程更新监听端口(比如新配置增加了监听 443 端口)
  4. Master 进程用新配置启动新的 Worker 子进程
  5. Master 进程向老 Worker 子进程发送 QUIT 信号
  6. 老 Worker 子进程关闭监听句柄,处理完当前连接后结束进程

在 1.11.11 的版本中,增加了 worker_shutdown_timeout 参数来设置优雅退出 Worker 进程的超时时间。

热升级流程

  1. 将旧 Nginx 文件换成新 Nginx 文件(注意备份)
  2. 向 Master 进程发送 USR2 信号
  3. Master 进程修改 pid 文件名,加后缀 .oldbin
  4. Master 进程用新 Nginx 文件启动新 Master 进程
  5. 向老 Master 进程发送 WINCH 信号,老 Master 进程会优雅关闭老 Worker 进程
  6. 此时老 Master 进程依然存活,如果出现问题需要回滚。向老 Master 进程发送 HUP,然后向新 Master 发送 QUIT 即可。(注意恢复备份文件)
  7. 正常升级后,通过 kill -QUIT 信号关闭老 Master 进程

新老 Master 进程,同时存在,那么是怎么同时监听端口的?

新老 Master 进程是父子进程,所以可以同时监听。

优雅关闭 Worker 进程

优雅关闭是指 HTTP 请求,如果代理的是 WebSocket、TCP、UDP,这时候 Nginx 是无法进行优雅关闭的。

  1. 设置定时器(这个功能默认不开启,配置文件有设置 worker_shutdown_timeout 才会生效)
  2. 关闭监听句柄
  3. 关闭空闲连接
  4. 在循环中等待全部连接关闭(如果设置了 worker_shutdown_timeout,超时后会强制关闭全部连接)
  5. 退出进程

更多信息可以参考官方文档 Starting, Stopping, and Restarting NGINX

原文转自博客 Nginx 进程和信号

共收到 1 条回复
huacnlee 将本帖设为了精华贴 12月02日 23:10

就这烂贴都能加星。。。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册