php-fpm重启导致的程序执行中断问题详解(2)

  • init script 是  /etc/init.d/php-fpm
  • 其中stop 是  killproc -p ${pidfile} php-fpm, 显然从日志结果来个是kill -TERM  . 文档里也说了默认信号就是TERMkillproc sends signals to all processes that use the spec­ified executable. If no signal name is specified, the signal SIGTERM is sent.

看下这个情况下nginx的反应

总结原因

  • 业务请求时执行完 sendPresent这个动作后 , 还没来得及写mongo库, php-fpm就刚好被 terminate 了,....  刚好赶上了

替代方案

  • 虽然php-fpm 没有解释 terminate 跟 graceful stop 的具体含义, 但猜的话前者是直接就终止程序的执行了,后者可能是温柔点,把处理中的请求里的所有操作都执行完再杀死。。。
  • 总之 SIGTERM terminate 调php 工作进程太粗暴了,应该要改一下比较好
  • 改成 SIGUSER2  reload 方式
  • 改成 SIGQUIT方式 ,把killproc -p ${pidfile} php-fpm 这句 改成 killproc -p ${pidfile} php-fpm -QUIT
  • php-fpm 的worker 是计数n次后就会杀掉重新拉一个,如果用reload感觉功能重复了,根本没必要定时重启了, 我还是选 graceful stop(SIGQUIT) 吧
  • 当然还有个问题时,为啥要配置个定时重启,将上面的内容发给sa看了

与sa 的问答

sa 说了3点意见

  • 建议看下 -QUIT 时,Nginx的状态码是否正常?另外在某种情况下,可能会造成 PHP-FPM 进程退出时间比较长,会影响部署吗?
  • 用 reload(SIGUSER2) 而不是用SIGTERM停掉再启动.
    我们之前的测试结果看 reload 之后,nginx会报 502,并不 graceful stop。建议做好测试确认,包括部署php代码时是不是 reload?Bug #60961 Graceful Restart (USR2) isn't very graceful
  • php-fpm每天定时重启脚本 这个定时脚本大概是在2012年部署的,当时是担心 PHP-FPM 存在内存泄漏的情况而添加的。到现在是不是还适用?建议找一台机器关掉定时脚本观察一段较长时间看看。

我回复

  • SIGQUIT 是否正常还不清楚,但现在的默认 SIGTERM 是立即停掉php 进程是肯定不正常的 --  从nginx error log 看,对于nginx 和 php-fpm已经建立好的连接,错误是 “104: Connection reset by peer”; 准备去连的是“111: Connection refused”;
  • “111: Connection refused” 是还可以接受的,连不上而已,用户稍后重试就可以;“104: Connection reset by peer” 这个就很难接受,这个错我理解的意思是连接已经建好了,php突然terminate了,然后发了个RST分节给nginx;背后就表示当前请求可能只执行了一半动作,还有动作没执行完,这可能就造成丢数据了。。。比如文章开头说的这个问题

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/6019.html