记php-fpm重启导致的一个bug

栏目: 数据库 · 发布时间: 5年前

内容简介:1是error log 丢日志了。 2是程序执行过程中操作完sendPresent后down掉了,导致没写入mongophp-fpm 是通过这里有提到,
  • 礼物订单对账时报警了,有笔订单在我们自己的mongo库里没有找到
  • php api 接口 /3/xx/vgift/send 调用礼物系统 sendPresent 接口完成送礼, 之后写mongo
  • 但是库里现在没记录,而且 php error log 也查不到任何mongo异常日志
  • 推初步断只有2个可能

1是error log 丢日志了。 2是程序执行过程中操作完sendPresent后down掉了,导致没写入mongo

  • 第一个情况工作多年的经验来看应该不至于,那就先根据第二种情况进行排查

排查

  • 先看下 php-fpm 的日志,看对应的时间点有没有什么异常,发现有线索
[wu.daolin@*****~]$ grep "2017 05:28" /var/log/php-fpm.log
[25-Jun-2017 05:28:01] NOTICE: Terminating ...

复制代码

熟悉下 php-fpm 的管理

php-fpm 是通过 php-fpm 这个命令进行管理的,我们先看下这个命令

man php-fpm

这里有提到, php-fpm then responds to several POSIX signals php-fpm 会对下面几个信号作(自己的)处理

  • SIGINT, SIGTERM: immediate termination
  • SIGQUIT: graceful stop
  • SIGUSR1: re-open log file
  • SIGUSR2: graceful reload of all workers + reload of fpm conf/binary

动手验证下

  • sudo kill -QUIT {php-fpm-pid}
[26-Jun-2017 13:58:22] NOTICE: Finishing ...                                                                                            
[26-Jun-2017 13:58:22] NOTICE: exiting, bye-bye!

复制代码
  • sudo kill -TERM {php-fpm-pid}
[26-Jun-2017 13:59:21] NOTICE: Terminating ...                                                                                          
[26-Jun-2017 13:59:21] NOTICE: exiting, bye-bye!
复制代码
  • sudo kill -USR2 {php-fpm-pid}
[26-Jun-2017 14:00:48] NOTICE: Reloading in progress ...                                                                                
[26-Jun-2017 14:00:48] NOTICE: reloading: execvp("/usr/sbin/php-fpm", {"/usr/sbin/php-fpm", "--daemonize"})                             
[26-Jun-2017 14:00:48] NOTICE: using inherited socket fd=8, "10.30.60.87:9000"                                                          
[26-Jun-2017 14:00:48] NOTICE: using inherited socket fd=8, "10.30.60.87:9000"                                                          
[26-Jun-2017 14:00:48] NOTICE: fpm is running, pid 12696                                                                                
[26-Jun-2017 14:00:48] NOTICE: ready to handle connections

复制代码

从以上验证结果推断

05:28:01 这个时间有人给php-fpm 发送了 SIGTERM 信号。 在这个点发生的很可能是个定时任务, 查了下crontab 果然是这样 28 5 * * * root /etc/init.d/php-fpm restart> /dev/null

看下我们的 php-fpm 管理

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

看下这个情况下nginx的反应

记php-fpm重启导致的一个bug

原因

  • 业务请求时执行完 sendPresent 这个动作后, php-fpm就刚好被 terminate 掉了, 导致订单没能写入mongo

后续替代方案分析

  • 虽然php-fpm 没有解释 terminategraceful stop 的具体含义, 但猜的话前者是直接就终止程序的执行了,后者可能是温柔点,把处理中的请求里的所有操作都执行完再杀死。。。
  • 首先 SIGTERM terminate掉 php 工作进程太粗暴了,应该要改一下比较好
  • 改成 SIGUSER2 reload 方式
  • 改成 SIGQUIT 方式 ,把 killproc -p ${pidfile} php-fpm 这句 改成 killproc -p ${pidfile} php-fpm -QUIT
  • php-fpm 的worker 是计数N次后就会自动杀掉重新拉一个,如果用reload感觉功能重复了,根本没必要定时重启了, 我还是选 SIGQUIT(graceful stop )试试吧
  • 当然还有个问题时,为啥要配置个定时重启,将上面的内容发给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 ;这意味当前请求可能只执行了部分动作,还有动作没执行,这可能就造成丢数据了。。。比如我们开头遇到的这个问题

  • reload 那个其实就是 -USR2信号,这个bug看起来还没解决。。。不过-USR2 应该说是偶现terminate,但 -TERM 是必现terminate

  • 现在代码部署是 同步代码+清理opcache和yac缓存, 不对php-fpm进程做操作

  • php-fpm 会自己对worker进程处理的请求数计数,达到一定数量就干掉再重新拉一个; 所以worker进程应该没有什么内存泄露的问题; manager 进程就不清楚了,但我想概率应该是极其低的。这个感觉很难去证伪啊。。。

  • 所以要不找3台机器, 一台用 -QUIT, 一台用 -USR2, 一台去掉这个定时任务;先观察下

  • sa 回复可以,我们自己看着办

后来

  • 改成 SIGQUIT 信号nginx里还是有 104: Connection reset by peer , 看来手册里说 SIGQUIT: graceful stop 也不能保证一次请求里的所有动作都执行完啊
  • 最终结果 去掉这个定时重启php-fpm 的任务 , 已经3个多月了,没发现问题,oh yeah~

参考文档


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

引爆社群

引爆社群

唐兴通 / 机械工业出版社华章科技 / 2015-3 / 49

科技延伸媒介,移动互联网技术催生了微信等各种新的媒体;媒介更新人文,新媒介让互联网重回社群时代;人文重塑商业规则,社群时代的商业模式与法则究竟是怎样的?我们应该如何去适应和应对?本书提出的“新4C法则”为此给出了解决方案。关于如何运用这个法则,本书给出了详尽的阐述。但是,要利用好这个法则,需要我们对它有深入的理解。 场景(Context):移动互联网时代场景为王,所有基于移动互联网的产品和服......一起来看看 《引爆社群》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试