nginx可以通过signals控制。默认,nginx主进程的进程ID写入“/usr/local/nginx/logs/nginx.pid”文件中。在配置阶段,这个名字可以被修改,或者在“nginx.conf”配置文件中,使用“pid”指令。
主进程支持下面的signals:
- TERM, INT - 快速关闭
- QUIT - 友好的关闭
- HUP - 修改配置,保持一个时区的改变(仅FreeBSD&Linux),友好的关闭旧的工作进程,使用新配置创建新的工作进程
- USR1 - 重新打开日志文件
- USR2 - 升级可执行文件(nginx主程序)
- WINCH - 友好的关闭所有的工作进程
单个的工作进程也可以通过signals控制,虽然并不需要,支持的signals有:
- TERM, INT - 快速关闭
- QUIT - 友好的关闭
- USR1 - 重新打开日志文件
- WINCH - 调试异常终止(需要开启debug_points指令)
改变配置
为了让nginx重新读取配置,”HUP“signal应该被发送给主进程。主进程首先对配置文件进行语法检测,之后尝试应用新的配置。打开日志文件,以及新的监听sockets。如果失败,回滚配置并继续使用旧的配置工作。如果生效,则开启新的工作进程,并发送消息给旧的工作进程,请求它们友好的关闭。旧的工作进程关闭监听的sockets并继续给旧的客户端提供服务,直到所有的客户端服务完毕,旧的工作进程关闭。
用下面的例子进行说明,假设nginx运行在 ”FreeBSD 4.x“,使用命令:
ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
输出如下:
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)
33128 33126 nobody 0.0 1364 kqread nginx: worker process (nginx)
33129 33126 nobody 0.0 1364 kqread nginx: worker process (nginx)
当”HUP“signal发送给nginx主进程,输出如下:
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)
上面可以发现,33129的工作进程,仍然在继续工作。一段时间后,输出如下:
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)
此时,所有的旧的工作进程,都已经全部关闭。
日志文件轮询
为了轮询日志文件,这些日志文件首先应该被重命名(轮询的日志文件命名有一定的规律)。接着,发送”USR1“signal给主进程。主进程将重新打开所有当前打开的日志文件,并且分配给它们一个没有特权的用户作为owner用户(工程进行的运行用户,例如上节中的nobody)。重新打开成功后,主进程关闭所有打开的文件,并发送消息给工作进程,要求它们去重新打开日志文件。工作进程打开新文件,并马上关闭旧文件。结果,旧文件几乎立马可用于后处理,例如:压缩。
在线升级可执行文件
为了升级服务器,新的可执行文件应该首先被写入到旧文件中。接着,发送”USR2“signal给主进程。主进程首先重命名 ”存储进程ID的文件“(/usr/local/nginx/logs/nginx.pid)为一个新文件,后缀是”.oldbin“(/usr/local/nginx/logs/nginx.pid.oldbin),接着,启动一个新的可执行文件,反过来,再启动新的工作进程:
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)
之后,所有的工作进程(新的&旧的)继续接收请求。如果 ”WINCH“ signal发送给第一个主进程,它将发送消息给它的子工作进程,请求它们友好的关闭,然后子工作进程开始关闭:
一段时间后,只有新的工作进程来处理请求:
注意:旧的主进程并没有关闭它监听的sockets,当需要时,它仍然能够开启它的子工作进程。如果,由于某些原因,新的可执行文件工作不正常,可执行下面的一个:
- 发送”HUP“signal给旧的主进程。旧的主进程,不用重新读取配置,并开启新的工作进程。之后,发送”QUIT“signal给新的主进程,新的进程将被友好的关闭。
- 发送”TERM“signal给新的主进程。将发送消息给它的工作进程,要求它们迅速退出,新的工作进程迅速退出(如果因为某些原因,新的进程并未退出,应该发送”KILL“signal,强制它们退出)。当新的主进程退出,旧的主进程将自动的开启新的工作进程。
如果新的主进程退出,然后旧的主进程忽略 ”.oldbin“ 后缀文件。
如果升级成功,之后应该发送”QUIT“signal给旧的主进程,最后,只有新的进程会被保留下来:
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)