nginx信号控制

本文深入探讨了Nginx的信号控制机制,包括如何通过信号实现配置更新、日志分隔和平滑升级。详细解释了主进程和工作进程如何响应不同信号,如HUP、USR1、USR2和WINCH,以及这些信号如何帮助实现服务的无缝更新和维护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


    在日常的开发维护中,我们经常使用nginx -s signal命令来完成nginx的优雅关闭/重载/平滑升级等。那么在稍微底层一点的层面如何去做的呢?
    实际上通过使用信号,我们也可以控制nginx,而我们平时使用的命令也是借助这些底层的信号来实现的。
    熟悉的nginx的同学基本上都知道,主进程的进程id默认写在/usr/local/nginx/logs/nginx.pid文件中。当然名称可以在配置参数时进行变动或者在nginx.conf中通过pid指令指定。
    nginx是由一个主进程和若干工作进程组成。主进程读取配置文件,并维护管理工作进程;工作进程则负责实际的请求处理。
    实际上在nginx运行过程中,两者也都是通过信号来控制的。下面做一下简单的支持介绍:
    主进程支持以下信号:

信号说明
TERM, INTfast shutdown
QUITgraceful shutdown
HUPchanging configuration, keeping up with a changed time zone (only for FreeBSD and Linux),
starting new worker processes with a new configuration, graceful shutdown of old worker processes
USR1re-opening log files
USR2upgrading an executable file
WINCHgraceful shutdown of worker processes

    工作进程支持以下信号:

信号说明
TERM, INTfast shutdown
QUITgraceful shutdown
USR1re-opening log files
WINCHabnormal termination for debugging (requires debug_points to be enabled)

更新配置

    切换配置时,向主进程发送HUP信号,nginx会重新读取配置。主进程首先会检查语法正确性,然后尝试应用新配置,也就是说要打开log文件和新的监听socket。
    如果失败,会回滚变动,继续使用老的配置工作;
    如果成功,则会创建新的进程,并向老的进程发送消息请求优雅关闭。老的进程会关闭监听socket,完成已有的终端服务连接,在所有请求任务完成后关闭。
   假设nginx运行在FreeBSD环境中,使用命令 ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep ‘(nginx|PID)’ 可以查看当前nginx相关进程。
    正常如下:

PIDPPIDUSER%CPUVSZWCHANCOMMAND
331261root0.01148pausenginx: master process /usr/local/nginx/sbin/nginx
3312733126nobody0.01380kqreadnginx: worker process (nginx)
3312833126nobody0.01364kqreadnginx: worker process (nginx)
3312933126nobody0.01364kqreadnginx: worker process (nginx)

    HUP信号发送后,如下:

PIDPPIDUSER%CPUVSZWCHANCOMMAND
331261root0.01164pausenginx: master process /usr/local/nginx/sbin/nginx
3312933126nobody0.01380kqreadnginx: worker process is shutting down (nginx)
3313433126nobody0.01368kqreadnginx: worker process (nginx)
3313533126nobody0.01368kqreadnginx: worker process (nginx)
3313633126nobody0.01368kqreadnginx: worker process (nginx)

    老的PID为33129的工作进程仍然工作。一段时间后,再次查看:

PIDPPIDUSER%CPUVSZWCHANCOMMAND
331261root0.01164pausenginx: master process /usr/local/nginx/sbin/nginx
3313433126nobody0.01368kqreadnginx: worker process (nginx)
3313533126nobody0.01368kqreadnginx: worker process (nginx)
3313633126nobody0.01368kqreadnginx: worker process (nginx)

日志分隔

    分割日志文件前,首先需要对文件进行重命名。然后会向主进程发送USR1信号。
    主进程作为持有者,会重新打开所有当前已打开的日志文件,然后将它们的权限置为nobody,所有的工作进程也是工作在这个权限下的。在重打开操作成功后,主进程关闭所有已打开的文件,并向工作进程发送消息要求他们重新打开日志文件。
    工作进程收到消息后,也会立刻关闭已打开的日志文件,并重新打开。
    这样,旧的文件基本可以立即进行后置处理,例如:压缩。

平滑升级

    升级服务器可执行文件,首先需要用新的可执行文件替换旧的可执行文件,然后向主进程发送USR2信号。
    主进程收到信号后,首先会将原有的进程文件nginx.pid重命名为nginx.pid.oldbin,然后运行新的可执行文件创建新的工作进程:

PIDPPIDUSER%CPUVSZWCHANCOMMAND
331261root0.01164pausenginx: master process /usr/local/nginx/sbin/nginx
3313433126nobody0.01368kqreadnginx: worker process (nginx)
3313533126nobody0.01380kqreadnginx: worker process (nginx)
3313633126nobody0.01368kqreadnginx: worker process (nginx)
3626433126root0.01148pausenginx: master process /usr/local/nginx/sbin/nginx
3626536264nobody0.01364kqreadnginx: worker process (nginx)
3626636264nobody0.01364kqreadnginx: worker process (nginx)
3626736264nobody0.01364kqreadnginx: worker process (nginx)

    然后所有的工作进程包括老的和旧的都会接收请求。在老的主进程接收到WINCH信号后,老的主进程发送消息要求它所属的所有工作进程优雅退出:

PIDPPIDUSER%CPUVSZWCHANCOMMAND
331261root0.01164pausenginx: master process /usr/local/nginx/sbin/nginx
3313533126nobody0.01380kqreadnginx: worker process is shutting down (nginx)
3626433126root0.01148pausenginx: master process /usr/local/nginx/sbin/nginx
3626536264nobody0.01364kqreadnginx: worker process (nginx)
3626636264nobody0.01364kqreadnginx: worker process (nginx)
3626736264nobody0.01364kqreadnginx: worker process (nginx)

    一段时间后只剩下新的工作进程处理请求:

PIDPPIDUSER%CPUVSZWCHANCOMMAND
331261root0.01164pausenginx: master process /usr/local/nginx/sbin/nginx
3626433126root0.01148pausenginx: master process /usr/local/nginx/sbin/nginx
3626536264nobody0.01364kqreadnginx: worker process (nginx)
3626636264nobody0.01364kqreadnginx: worker process (nginx)
3626736264nobody0.01364kqreadnginx: worker process (nginx)

    需要注意的是,老的主进程不会关闭它的监听sockets,如果需要还可以用来创建它自己的工作进程。当新的可执行文件没有按照预期运作时,可以采用以下措施:

  • 向老的主进程发送HUP信号。老的主进程会再创建它自己的工作进程,此时不需要再读取配置文件。然后老的主进程会向新的主进程发送QUIT信号,优雅关闭新的主进程下的工作进程。
  • 向新的主进程发送TERM信号。新的主进程会发送消息要求所属的所有新的工作进程立刻退出,而对应的工作进程实际也基本如此(如果新的进程由于某些原因,没有退出,那么我们应该使用kill信号指令强制杀死对应进程)。当新的主进程退出后,老的主进程会自动创建自己的工作进程。

    如果新的主进程退出服务,老的进程会把已经添加.oldbin后缀的原主进程记录文件名称改回来。
    如果升级成功,则会向老的主进程发送QUIT信号,只留下新的主进程:

PIDPPIDUSER%CPUVSZWCHANCOMMAND
362641root0.01148pausenginx: master process /usr/local/nginx/sbin/nginx
3626536264nobody0.01364kqreadnginx: worker process (nginx)
3626636264nobody0.01364kqreadnginx: worker process (nginx)
3626736264nobody0.01364kqreadnginx: worker process (nginx)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值