> 文章列表 > php:php-fpm平滑重启为什么无效

php:php-fpm平滑重启为什么无效

php:php-fpm平滑重启为什么无效

一、问题

        今天修改了fpm一些配置,需要上线重启fpm,但是发现一瞬间出现很多502的错误请求,查看日志发现以下错误

fpm:重启日志

 nginx:错误日志

2023/04/23 15:19:00 [error] 9#0: *1893053661 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: *****, server: ***.com

2023/04/23 15:19:00 [error] 9#0: *1893053661 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: *****, server: ***.com

二、原因

        通过排查,最后发现:在重新加载配置文件期间,PHP-FPM master 进程会关闭所有已有的子进程,重新创建新的子进程并加载新的配置文件。在这个过程中,如果有客户端发出请求,请求就会失败并返回 502 错误。

  测试案例:

<?phpecho "测试开始";sleep(10);echo "测试结束";

 进行访问,然后在访问中, 进行 kill -USR2 maserid,页面就会出现502

三、解决方案

  1. 逐步平滑重启:使用 kill -USR2 命令时,可以使用 php-fpm -t 命令测试新配置是否正确,然后使用 kill -WINCH 命令逐步平滑重启 PHP-FPM,以避免一瞬间关闭所有子进程造成的服务中断。

  2. 配置进程平滑重启:在 PHP-FPM 配置文件中,你可以设置 process_control_timeout 参数,以控制每个子进程退出的最大时间。在重新加载配置文件时,master 进程会等待所有子进程在这个时间内优雅地关闭,避免服务中断。(这种方法在一篇向官方反馈的bug中也有提到,其中建议是[2013-02-13 15:57 UTC] phpbugs at oops dot mooo dot com Try setting process_control_timeout to something higher than 0. 但是切记process_control_timeout配置并不是所有php版本都支持,使用前一定要测试自己的php版本是否支持该配置,目前一般都是7.2以上才支持

    process_control_timeout = 20s;process_control_timeout 设置子进程接受主进程复用信号的超时时间。可用单位:s(秒)、m(分)、h(小时)或者 d(天)。默认单位:s(秒)。参数缺省是 0。
    即reload的时候,如果有正在执行的请求进程便会等待该进程设置的时长。而其他进程直接就结束掉。等待正在执行的进程执行完或者是超过了设置的时间后fpm的master进程才开始生成新的fpm worker进程。
  3. 使用进程管理工具:使用进程管理工具,如 Supervisor、Systemd、Upstart 等,来启动和管理 PHP-FPM 进程,可以更好地控制进程的生命周期和平滑重启,从而减少服务中断的风险。

       

总之,在重新加载 PHP-FPM 配置文件时,需要考虑到服务中断的可能性,采取适当的措施来减少风险,并尽可能地保证服务的可用性。