/ Nginx

Nginx平滑升级原理

今天要把一台线上服务器的nginx升级至新版本,因为访问量比较大,而且跑的是比较重要的服务,所以不允许出现请求拒绝的情况。同事给了一段shell脚本:

mv nginx nginx.old mv nginx.new nginx oldpid=$(ps aux|grep "nginx: master process"|grep -v grep |awk '{print $2}') echo $oldpid>$file kill -USR2 $oldpid while (true) do sleep 2 pidcount=$(ps aux|grep "nginx: master process"|grep -v grep |wc -l) [ "$pidcount" = "2" ] && kill -WINCH $oldpid && break done while (true) do sleep 2 pidcount=$(ps -ef|grep $oldpid|grep -v grep |wc -l) [ "$pidcount" = "2" ] && kill -QUIT $oldpid && break done

注:这个脚本在只有一个nginx在运行时才可以直接使用。

前面两个mv看懂了,后面的几个kill却不知道是干的啥,回家之后就百度了一下下,大致了解了这些操作的目地。

首先我查的是kill命令以及相关的信号,相关的信号是

USR2:用户自定义信号2

WINCH:窗口大小改变

QUIT:退出程序

看完这个就完全摸不着头脑,nginx平滑升级和窗口大小改变有啥关系啊,那个用户自定义信号又是什么玩意。

于是再次搜索”nginx usr2″

这回找到靠谱的资料,在nginx官方wiki上有具体说明http://wiki.nginx.org/CommandLine

nginx应该是重写了对信号的处理,在nginx master进程收到USR2信号时会将当前运行的nginx master进程号写到log/nginx.pid.oldbin,然后启动一个新的nginx进程(这个已经是新的程序了),这个时候两个nginx实例共同去处理用户的请求。

当旧nginx master进程收到WINCH信号时,nginx会优雅地停止服务,即:停止接收新的请求,但是不会终止已经在处理的请求。

一段时间后,旧nginx的所有worker进程全部退出,只剩下master进程,而用户请求全部都由新的nginx进程处理。这个时候就可以给旧nginx master进程发送QUIT信号,旧nginx进程完全退出,至此平滑升级完成。

wiki中也给出了nginx对其他信号的处理:

TERM, INTQuick shutdown
QUITGraceful shutdown
KILLHalts a stubborn process
HUPConfiguration reload Start the new worker processes with a new configuration Gracefully shutdown the old worker processes
USR1Reopen the log files
USR2Upgrade Executable on the fly
WINCHGracefully shutdown the worker processes
Nginx平滑升级原理
Share this