翻译自 原文

nginx可以通过信号来控制。master进程的进程ID默认被写入到/usr/local/nginx/logs/nginx.pid中。该路径名可以在配置时更改,或者直接在nginx.conf中使用 pid。master进程支持以下信号:

TERM,INT 快速关闭
QUIT 优雅的关闭
HUP 更改配置,更新时区(只适用于FreeBSD和Linux),使用新的配置启动新的woker进程,优雅的关闭旧的worker进程。
USR1 重新打开日志文件
USR2 更新nginx
WINCH 优雅的关闭worker进程。

单个的worker进程也可以通过信号来控制,虽然这并不是必须的。支持的信号如下:

TERM,INT 快速关闭
QUIT 优雅的关闭
USR1 重新打开日志文件
WINCH 非正常终止进程来调试(需要开启 debug_points 选项)

注:

  • 优雅的关闭:worker进程会在关闭之前为已建立的连接提供完服务。
  • 快速关闭:所有的worker进程立刻关闭,即使还有未提供完服务的连接。

更改配置

为了能让nginx重新读取配置文件,我们可以向master进程发送HUP信号。master进程会首先验证语法的正确性,然后尝试应用新的配置,也就是,打开新的日志文件和新的套接字。如果尝试失败,它会回滚更改并继续使用原来的配置文件。如果尝试成功,它会开启新的worker进程,并向旧的worker进程发送信号,要求它们进行”优雅的关闭”。而后,旧的worker进程会关闭套接字并继续为已建立的连接提供服务。等到所有的连接都服务完了,旧的worker进程才会关闭。

让我们通过以下的例子演示以下。假设nginx运行在FreeBSD 4.x上,并使用以下命令:

1
ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'

输出如下:

1
2
3
  PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126 1 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
33127 33126 nobody 0.0 1380 kqread nginx: worker process (nginx)

如果此时向master进程发送HUP命令,输出会变成下面这样:

1
2
3
4
5
6
  PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
33129 33126 nobody 0.0 1380 kqread nginx: worker process is shutting down (nginx)
33134 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33135 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33136 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)

PID为33129的进程会继续工作,它退出后输出如下:

1
2
3
4
5
  PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
33134 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33135 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33136 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)

切割日志文件

原文说的不太详细,该部分的详细介绍请见: 链接

不重启,更新nginx的可执行文件

为了更新nginx的可执行文件,新的可执行文件需要先替换掉旧的可执行文件。而后,向master进程发送USR2信号。master进程先将nginx.pid重命名为nginx.pid.oldbin,而后它会启动一个新的master进程,新的master进程再启动新的worker进程。

1
2
3
4
5
6
7
8
9
  PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
33134 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33135 33126 nobody 0.0 1380 kqread nginx: worker process (nginx)
33136 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
36264 33126 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36266 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36267 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)

之后,新旧worker进程都继续接受请求。如果现在向旧master进程发送”WINCH”信号,它会向它的worker进程发送信号,要求它们优雅的关闭,而后这些woker会退出:

1
2
3
4
5
6
7
  PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
33135 33126 nobody 0.0 1380 kqread nginx: worker process is shutting down (nginx)
36264 33126 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36266 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36267 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)

当在Linux使用的是”rtsig”方法时,当向旧master进程发送”WINCH”信号后,新的worker进程可能不会接受客户端请求。这种情况下,可以继续向新master进程发送USR1信号,直到新的worker进程开始接受客户端请求。

一段时间后,会只有新的worker进程会处理客户端请求:

1
2
3
4
5
6
  PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
36264 33126 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36266 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36267 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)

需要特别说明的是,旧master进程不会关闭它的套接字,如果需要的话,我们可以让它重新启动worker进程。如果由于某些原因,新的可执行文件不能正常的工作,可以使用以下的方式来解决:

  • 向旧master进程发送”HUP”信号。旧master进程会开启新的worker进程(不会再读取配置文件)。此时再向新的master进程发送QUIT信号,它创建的worker进程会“优雅的关闭”。
  • 向新的master进程发送TERM信号。它会向它的worker进程发送信息,要求它们立刻退出。(如果由于某些原因这些新的进程没有退出,需要向这些进程发送”KILL”信号,强制它们推出。)当新的master进程。

如果新的master进程推出了,旧的master进程会忽略nginx.pid的后缀–.oldbin。

如果升级成功,向旧的master进程发送QUIT信号,此时,只剩下新的进程:

1
2
3
4
5
PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
36264 1 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36266 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36267 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)