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


Posted in PHP onApril 29, 2019

背景和初步排查

  • 订单业务对账时报警了,有笔订单在我们自己的mongo库里没有找到
  • 业务接口  /3/xx/vgift/send 调用礼物系统  sendPresent 接口完成送礼, 之后写mongo,但是php error log 里却查不到任何mongo异常日志
  • 写mongo没有异常,但是库里却没记录,推断只有2个可能

1是error log 丢日志了
2是程序执行过程中操作完sendPresent后down掉了,导致没写入mongo
-第一个情况工作多年的经验来看应该不至于,那就先根据第二种情况继续查吧

  • 那就去看下php-fpm 的日志,看对应的时间点有没有什么异常
[wu.daolin@web001.m6~]$ 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 12583

[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信号,在这个点发生很可能是个定时任务, 确认果然是这样 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  . 文档里也说了默认信号就是TERMkillproc 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重启导致的程序执行中断问题详解

总结原因

  • 业务请求时执行完 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;背后就表示当前请求可能只执行了一半动作,还有动作没执行完,这可能就造成丢数据了。。。比如文章开头说的这个问题
  • 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~

参考文档

  • php-fpm signal handler
  • php-fpm init script
  • killproc man page

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP里的中文变量说明
Jul 23 PHP
使用PHP破解防盗链图片的一个简单方法
Jun 07 PHP
PHP中常用的字符串格式化函数总结
Nov 19 PHP
PHP判断一个gif图片是否为动态图片的方法
Nov 19 PHP
PHP PDO fetch 模式各种参数的输出结果一览
Jan 07 PHP
php基于单例模式封装mysql类完整实例
Oct 18 PHP
yii2.0整合阿里云oss删除单个文件的方法
Sep 19 PHP
Laravel 5.4.36中session没有保存成功问题的解决
Feb 19 PHP
redis+php实现微博(一)注册与登录功能详解
Sep 23 PHP
laravel Validator ajax返回错误信息的方法
Sep 29 PHP
在Laravel 的 Blade 模版中实现定义变量
Oct 14 PHP
浅析PHP反序列化中过滤函数使用不当导致的对象注入问题
Feb 15 PHP
详解提高使用Java反射的效率方法
Apr 29 #PHP
Thinkphp整合阿里云OSS图片上传实例代码
Apr 28 #PHP
详解php中生成标准uuid(guid)的方法
Apr 28 #PHP
PHP写API输出的时用echo的原因详解
Apr 28 #PHP
PHP+mysql防止SQL注入的方法小结
Apr 27 #PHP
PHP常用工具函数小结【移除XSS攻击、UTF8与GBK编码转换等】
Apr 27 #PHP
PHP操作路由器实现方法示例
Apr 27 #PHP
You might like
常用的php对象类型判断
2008/08/27 PHP
PHP获取163、gmail、126等邮箱联系人地址【已测试2009.10.10】
2009/10/11 PHP
PHP中spl_autoload_register函数的用法总结
2013/11/07 PHP
PHP利用header跳转失效的解决方法
2014/10/24 PHP
php 流程控制switch的简单实例
2016/06/07 PHP
PHP基于自定义函数实现的汉字转拼音功能实例
2017/09/30 PHP
javascript EXCEL 操作类代码
2009/07/30 Javascript
JS 加入收藏夹的代码(主流浏览器通用)
2013/05/13 Javascript
JS动态添加Table的TR,TD实现方法
2015/01/28 Javascript
Angular.JS中的指令引用template与指令当做属性详解
2017/03/30 Javascript
微信小程序 新建登录页并实现tabBar隐藏
2017/06/13 Javascript
Vue中引入样式文件的方法
2017/08/18 Javascript
分享5个顶级的JavaScript Ajax组件库
2018/09/16 Javascript
vue-router 起步步骤详解
2019/03/26 Javascript
Layui实现数据表格默认全部显示(不要分页)
2019/10/26 Javascript
解决vue prop传值default属性如何使用,为何不生效的问题
2020/09/21 Javascript
[00:36]DOTA2勇士令状莱恩声望物品——冥晶之厄展示
2018/05/25 DOTA
Python写的创建文件夹自定义函数mkdir()
2014/08/25 Python
Python3中多线程编程的队列运作示例
2015/04/16 Python
Django的数据模型访问多对多键值的方法
2015/07/21 Python
Python实现动态图解析、合成与倒放
2018/01/18 Python
Python 最大概率法进行汉语切分的方法
2018/12/14 Python
python 通过SSHTunnelForwarder隧道连接redis的方法
2019/02/19 Python
浅谈Django中view对数据库的调用方法
2019/07/18 Python
Python实现剪刀石头布小游戏(与电脑对战)
2019/12/31 Python
用opencv给图片换背景色的示例代码
2020/07/08 Python
python进度条显示之tqmd模块
2020/08/22 Python
基于Python的图像阈值化分割(迭代法)
2020/11/20 Python
Python 将代码转换为可执行文件脱离python环境运行(步骤详解)
2021/01/25 Python
HTML5触摸事件演化tap事件介绍
2016/03/25 HTML / CSS
美国知名珠宝首饰品牌:Gemvara
2017/10/06 全球购物
运动鞋、足球鞋和慕尼黑球衣:Sport Münzinger
2019/08/26 全球购物
员工工作表扬信范文
2014/01/13 职场文书
中学教师师德师风承诺书
2015/04/28 职场文书
运动会闭幕式主持词
2015/07/01 职场文书
电脑关机速度很慢怎么办 提升电脑关机速度设置教程
2022/04/08 数码科技