Nginx是父子进程的通信是通过信号进行管理的,使用ps -ef可以看到当前进程的ID和其父进程的ID。
[root@www ~]# ps -ef | grep nginx
root 1961 1 0 11:14 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 1965 1961 0 11:14 ? 00:00:00 nginx: worker process
当我们更新了nginx的配置文件都会使用-reload将配置文件进行重载。在使用这条命令的时候希望ngnix不能停止服务,始终还在处理新的请求的同时将nginx的旧的配置文件更新为新的配置文件。
这样一个功能对于nginx非常有必要,但是在高并发的场景下会发现使用-s reload之后worker进程的数量变多了,这其实是老的配置的worker进程长时间没有退出。
使用-s reload会把之前的worker进程优雅的退出然后再使用新的配置项去启动新的worker进程,我这里没有改变配置,但是可以看到,老的一个worker子进程将会退出还会生成新的worker子进程。
[root@www ~]# /usr/local/nginx/sbin/nginx -s reload
[root@www ~]# ps -ef | grep nginx
root 1961 1 0 11:14 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 1971 1961 0 11:15 ? 00:00:00 nginx: worker process
可以看到之前的子进程1965现在已经不在了,反而1961启动1971子进程。reload信号和HUP信号是相同的,现在向nginx的master进程发送HUP信号,是不是会发生相同的结果呢?
[root@www ~]# kill -HUP 1961
[root@www ~]# ps -ef | grep nginx
root 1961 1 0 08:32 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 1935 1961 0 11:41 ? 00:00:00 nginx: worker process
这里说一下为什么会打开新的监听端口呢? 因为可能在nginx.conf当中引入了新的端口号,所有worker进程是master进程的子进程,子进程会继承父进程所有打开的端口,这个是Linux操作系统所定义的。
同时注意一下顺序,是先启动新的worker子进程再向老的worker进程发送QUIT信号。而不是先向老的worker进程发送QUIT信号再启动新的worker进程,之后新的连接只会到新的worker进程。
master上面原先有四个绿色的子进程 ,它们使用的是老的配置。当更改了nginx的配置文件以后通过-reload或者SIGHUP信号。执行了reload之后master会用新的配置文件启动四个新的黄色的worker子进程。这个时候是新老worker子进程同时存在的。老的worker子进程在正常的情况下它会在处理好已经建立好的连接跑的请求之后关闭这个连接,哪怕这个连接是keepalived的请求也会正常的关闭。
但是异常的情况,比如一些异常的请求出了问题了,客户端长时间没有处理就会导致这个处理的请求长时间驻留在老的worker子进程上面,这个worker进程就会一直的存在。新的连接已经跑在了黄色的新的worker子进程上面所以影响不大。唯一可能导致绿色的老的worker子进程长时间存在,但是也只影响已经存在的连接,不会影响新的连接。
在新的版本中可以加入配置项来设置定时器,在master启动新的worker子进程计数器开始计数,在规定的时间到了,连接在老的worker进程里面还没有退出,立刻强制的将老的worker子进程退出!
语法:worker_shutdown_timeout time;
默认值:无
语境:main
此指令在v1.11.11中出现。用于设置安全地结束一个worker进程的超时时间。
当安全结束一个worker进程时,会停止对worker进程分配新连接,并等待他处理完当前的任务后再退出,如果设置了超时时间,超时后nginx会强制关闭worker进程的连接。
[root@www ~]# ps -ef | grep nginx
root 1961 1 0 11:14 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 1976 1961 0 11:17 ? 00:00:00 nginx: worker process
向对应的stop,quit也有信号,在worker进程退出的时候会向master进程发送信号,当父进程收到信号之后知道子进程退出了,会新启worker进程来维持配置文件里面配置的worker进程的进程数
[root@www ~]# kill -SIGTERM 1976
[root@www ~]# ps -ef | grep nginx
root 1961 1 0 11:14 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody 1980 1961 0 11:22 ? 00:00:00 nginx: worker process
可以看到1976进程已经退出了,但是nginx又重新启动了新的进程1980。所以在命令行的命令是父进程对子进程发送信号而已。