unix – 如何在不丢弃任何请求的情况下升级Nginx?
作者:互联网
If you need to replace nginx binary
with a new one (when upgrading to a
new version or adding/removing server
modules), you can do it without any
service downtime – no incoming
requests will be lost.
我的同事和我想弄清楚:这是怎么回事?我们知道(我们认为):
>一次只能有一个进程在端口80上侦听
> Nginx创建一个套接字并将其连接到端口80
>父进程及其任何子进程都可以绑定到同一个套接字,这就是Nginx可以让多个工作者子进程响应请求的方式
我们还对Nginx进行了一些实验,如下所示:
>将kill -USR2发送到当前主进程
>反复运行ps -ef | grep独角兽看到任何独角兽进程,有自己的pid和他们的父pid
>观察新的主进程首先是旧主进程的子进程,但是当旧主进程消失时,新主进程的ppid为1.
所以显然新的主进程可以在它们运行时监听与旧主进程相同的套接字,因为在那时,新主进程是旧主进程的子进程.但不知何故,新的主进程可以成为……呃…没有人的孩子?
我认为这是标准的Unix东西,但我对进程和端口和套接字的理解非常模糊.任何人都能更详细地解释一下吗?我们的任何假设是错误的吗?还有一本我能阅读的书真的可以理解这些东西吗?
解决方法:
具体如下:http://www.csc.villanova.edu/~mdamian/Sockets/TcpSockets.htm描述了TCP套接字的C库.
我认为关键是在持有套接字文件描述符的进程分支之后,父进程和子进程都能够在其上调用accept().
所以这就是流程. Nginx正常启动:
>调用socket()和bind()以及listen()来设置一个由文件描述符(整数)引用的套接字.
>启动一个在循环中调用文件描述符上的accept()的线程来处理传入的连接.
然后Nginx分叉.父母像往常一样继续运行,但是孩子立即执行新的二进制文件.擦除旧程序,内存和运行线程,但继承打开文件描述符:请参阅http://linux.die.net/man/2/execve.我怀疑exec()调用将打开文件描述符的编号作为命令行参数传递.
孩子,作为升级的一部分开始:
>从命令行读取打开文件描述符的编号.
>启动一个在循环中调用文件描述符上的accept()的线程来处理传入的连接.
>告诉父母排水(停止接受(),完成现有连接),并死亡.
标签:nginx,unix,internals 来源: https://codeday.me/bug/20190621/1255547.html