简介
Nginx是一个强大的Web服务器和反向代理,被用来为世界上许多最流行的网站提供服务。在本指南中,我们将演示如何在不丢失客户端连接的情况下,就地升级Nginx可执行文件。
前提条件
在开始本指南之前,你的服务器上应该有一个非root用户,并配置了sudo 的权限。你还需要安装Nginx。
升级如何进行
Nginx的工作原理是在服务启动时产生一个主进程。主服务反过来又产生一个或多个工作进程,处理实际的客户端连接。Nginx被设计成在收到来自系统的特定低级信号时执行某些动作。使用这些信号,可以使你有机会在不丢失客户端连接的情况下,就地升级Nginx或其配置。
Nginx提供的安装和升级脚本被设计为在启动、停止和重新启动Nginx时发送这些信号。然而,手动发送这些信号可以让你审计升级,并在出现问题时迅速恢复。如果你是从源码安装Nginx,或者不依赖软件包管理器配置服务,这也将提供一个优雅升级的选项。
将使用以下信号。
USR2:这就产生了一组新的主程序/工作程序,而不影响旧的程序。WINCH:这告诉Nginx主进程优雅地停止其相关的工作实例。HUP::这告诉Nginx主进程重新读取其配置文件,用遵守新配置的工人进程替换。如果新旧两个主进程都在运行,向旧的主进程发送这个命令,将使用其原来的配置生成工作进程。QUIT:这将优雅地关闭一个主进程及其工作进程。TERM:快速关闭主站及其工作进程。KILL::这将立即杀死一个主站和它的工作器,而不进行任何清理。
寻找Nginx进程的PID
为了向各个进程发送信号,我们需要知道目标进程的PID。有两种方法可以找到这个。
首先,你可以使用ps 工具,然后在grep ,在结果中找到Nginx。这可以让你看到主进程和工作进程。
ps aux | grep nginx
output
root 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
nginx 16654 0.0 0.9 151820 8156 ? S 21:48 0:00 nginx: worker process
sammy 16688 0.0 0.1 221928 1164 pts/0 S+ 21:48 0:00 grep --color=auto nginx
第二列,高亮显示的是所选进程的PID。最后一栏说明第一个结果是Nginx主进程。
找到Nginx主进程的PID的另一个方法是打印出/run/nginx.pid 文件的内容。
cat /run/nginx.pid
output
16653
如果有两个Nginx主进程在运行,旧的那个将被移到/run/nginx.pid.oldbin 。
生成一个新的Nginx主进程/工作集
实现优雅更新的第一步是实际更新Nginx软件包和/或二进制文件。使用适合你的Nginx安装的任何方法,无论是通过软件包管理器还是源代码安装。
在新的二进制文件到位后,你可以生成第二组主进程/工作进程,使用新的可执行文件。
你可以通过直接向你查询的PID号码发送USR2 信号来实现这一目的(确保在这里替换你自己的Nginx主进程的PID)。
sudo kill -s USR2 16653
或者,你可以直接读取并替换存储在你的PID文件中的值,像这样。
sudo kill -s USR2 `cat /run/nginx.pid`
如果你检查你的运行进程,你会看到现在有两套Nginx主进程和工作进程。
ps aux | grep nginx
output
root 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
nginx 16654 0.0 0.9 151820 8156 ? S 21:48 0:00 nginx: worker process
root 16699 0.0 1.5 119164 12732 ? S 21:54 0:00 nginx: master process /usr/sbin/nginx
nginx 16700 0.0 0.9 151804 8008 ? S 21:54 0:00 nginx: worker process
sammy 16726 0.0 0.1 221928 1148 pts/0 R+ 21:55 0:00 grep --color=auto nginx
你还可以看到,原来的/run/nginx.pid 文件已经被移到了/run/nginx.pid.oldbin ,较新的主进程的PID已经被写到了/run/nginx.pid 。
tail -n +1 /run/nginx.pid*
output
==> /run/nginx.pid <==
16699
==> /run/nginx.pid.oldbin <==
16653
现在你可以使用这些文件中包含的PID向任何一个主进程发送信号。
在这一点上,两套主进程/工作进程都可以运行,并且能够为客户请求提供服务。第一组使用的是原始的Nginx可执行文件和配置,第二组使用的是较新的版本。它们可以继续并排运行,但为了保持一致性,我们应该开始过渡到新的一组。
关闭第一个主站的工作者
为了开始过渡到新的集合,首先要做的是停止原来主站的工作进程。原有的工作程序将处理完所有当前的连接,然后退出。
通过向他们的主进程发出WINCH 信号来停止原集的工作者。
sudo kill -s WINCH `cat /run/nginx.pid.oldbin`
这将让新的主进程的工作者单独处理新的客户连接。旧的主进程仍在运行,但没有工人。
ps aux | grep nginx
output
root 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
root 16699 0.0 1.5 119164 12732 ? S 21:54 0:00 nginx: master process /usr/sbin/nginx
nginx 16700 0.0 0.9 151804 8008 ? S 21:54 0:00 nginx: worker process
sammy 16755 0.0 0.1 221928 1196 pts/0 R+ 21:56 0:00 grep --color=auto nginx
这可以让你在新的工作器接受连接时对其进行单独审计。
评估结果并采取下一步措施
在这一点上,你应该测试和审核你的系统,以确保没有问题的迹象。你可以让你的配置保持在这个状态,只要你想确保新的Nginx可执行文件没有错误,并且能够处理你的流量。
下一步将完全取决于你是否遇到了问题。
如果你的升级是成功的
如果你的新组工人没有遇到问题,你可以安全地关闭旧的主进程。要做到这一点,向旧的主进程发送QUIT 信号。
sudo kill -s QUIT `cat /run/nginx.pid.oldbin`
旧的主进程将优雅地退出,只留下新的一组Nginx主进程/工作程序。在这一点上,你已经成功地对Nginx进行了原地二进制更新,没有中断客户端的连接。
如果你的升级不成功
如果你的新工作集似乎有问题,你可以过渡到旧的配置和二进制。只要你没有QUIT 旧的主进程,就可以做到这一点。
最好的方法是通过发送HUP 信号来重启你的旧主进程的工作者。通常情况下,当你向Nginx主进程发送HUP 信号时,它将重新读取其配置文件并启动新的工作。然而,当目标是一个老的主站时,它将使用原来的工作配置生成新的工作器。
sudo kill -s HUP `cat /run/nginx.pid.oldbin`
现在你应该回到有两套主站/工作站进程的状态。
ps aux | grep nginx
output
root 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
nginx 16654 0.0 0.9 151820 8156 ? S 21:48 0:00 nginx: worker process
root 16699 0.0 1.5 119164 12732 ? S 21:54 0:00 nginx: master process /usr/sbin/nginx
nginx 16700 0.0 0.9 151804 8008 ? S 21:54 0:00 nginx: worker process
sammy 16726 0.0 0.1 221928 1148 pts/0 R+ 21:55 0:00 grep --color=auto nginx
最新的工作者与旧的主站相关联。在这一点上,两套工作程序都将接受客户端连接。现在,通过发送QUIT 信号,停止较新的、有问题的主进程和它的工作者。
sudo kill -s QUIT `cat /run/nginx.pid`
你应该回到你的旧主进程和工作者。
ps aux | grep nginx
output
root 16653 0.0 0.2 119160 2172 ? Ss 21:48 0:00 nginx: master process /usr/sbin/nginx
nginx 16654 0.0 0.9 151820 8156 ? S 21:48 0:00 nginx: worker process
sammy 16688 0.0 0.1 221928 1164 pts/0 S+ 21:48 0:00 grep --color=auto nginx
原来的主进程将重新获得其PID的/run/nginx.pid 文件。
如果这个方法由于任何原因没有奏效,你可以尝试向新的主服务器发送TERM 信号,这应该会启动一个关闭。这应该会停止新的主服务器和任何工作程序,同时自动踢开旧的主服务器以启动其工作程序。如果有严重的问题,并且有问题的工作程序没有退出,你可以给它们每个人发送一个KILL 信号来清理。然而,这应该是最后的手段,因为它将切断连接。
在过渡到旧的二进制文件后,记住你的系统上仍然安装着新的版本。你应该删除有问题的版本,并回滚到以前的版本,这样Nginx在重启时就能顺利运行。
总结
到现在,你应该能够将你的机器从一个Nginx二进制文件无缝过渡到另一个。Nginx能够处理两个主程序/工作程序集,同时保持它们之间的关系信息,这为我们提供了升级服务器软件的能力,而无需将服务器机器下线。