#工作总结#对于周末服务器502问题的分享会总结笔记

一、问题场景复现:
 
  周六早上9:55左右,ZR的APP间接性出现首页、列表页和详情页无法访问的问题,提示用户“后台接口异常”。通过排查得知,部分接口请求返回的结果是502,通过进一步排查,得知出现502的原因是因为后台应用服务器一共两台,其中一台的php-fpm服务异常,无法处理用户请求导致。(该台服务器周五的时候,运维同事修改过日志归档整理脚本,也是由于这个改动引起的这个问题,后面会说明)
 
二、处理方式:
 
  排查到这个原因后,立即将服务器的php-fpm服务进行了重启操作,解决了线上服务几乎不可用的状态。
  (有问题的正确做法是:摘掉有问题的机器,让正常服务的机器对外提供服务。然后对有问题的机器进行问题排查,分析并找到问题产生的原因,并对问题进行总结和修复,并对其他机器进行排查是否同样有此问题或可能会产生此问题,避免同样的问题再次发生)
 
三、问题回顾及分析:
 
  在得知线上的问题产生的原因是php-fpm服务挂掉引起的,那是什么原因导致的fpm服务器被“处死”了呢?
  通过运维的监控数据分析得知,被改过归档日志脚本的这台机器,在服务器做完归档日志之后,fpm的数量陆续减少,而且在稍后一个时间段有断点,最后在9点50分左右变为0,即线上问题爆发的时间点前后。

112.png

 
然后对修改的脚本日志进行检查,发现日志归档脚本里对fpm进行reload的命令里,有这样一个命令:
 

113.png

 
 
其中,用到的是(-HUP信号)
kill -HUP `cat $PIDFILE` || echo -n " can't reload"








然而,PHP官方源码中提供的PHP-FPM reload方法中,用的则是(-USR2信号):
kill -USR2 `cat $php_fpm_PID`

114.png

 
PHP官方源码截图(https://github.com/php/php-src/blob/master/sapi/fpm/init.d.php-fpm.in
 
问题就出在这!PHP-FPM对HUP和SUR2这两个信号处理方式上的区别。


在PHP-FPM中,对于HUP信号,会进行的操作是重启fpm服务,而USR2信号,则是仅仅对fpm的配置文件进行重载,并不会重启fpm的服务(master)。


 
对于nginx的这些信号,不同的服务有其各自的处理方式,然而,FPM并没有像大家预想的那样,正是这个差异,让FPM服务在这个脚本命令执行之后,master主服务被“杀死”,而且没有顺利重新启动(报错,报端口9000被占用,因为此时,fpm的works们并没有停止服务,还在接受这请求)。
 
FPM如何处理各个指令,可以研究源码,地址:https://github.com/php/php-src/blob/e3feeba3aedd8e4347fefa315effd7d4f9fa0ca1/sapi/fpm/fpm/fpm_signals.c 
 
来看一条来自维基百科的解释(https://zh.wikipedia.org/wiki/SIGUSR1%E5%92%8CSIGUSR2 ):


SIG是信号名的通用前缀。USR是user-defined的缩写,即用户定义的。
SIGUSR1和SIGUSR2的含义在POSIX中没有定义。它们的用途在不同的程序中可能有所不同。
 
USR1亦通常被用来告知应用程序重载配置文件;
例如,向Apache HTTP服务器发送一个USR1信号将导致以下步骤的发生:停止接受新的连接,等待当前连接停止,重新载入配置文件,重新打开日志文件,重启服务器,从而实现相对平滑的不关机的更改。


 
然而,对HUP命令的常规描述是:


kill -HUP pid 或者 killall -HUP pName:
其中pid是进程标识,pName是进程的名称。如果想要更改配置而不需停止并重新启动服务,可以使用上面两个命令。在对配置文件作必要的更改后,发出该命令以动态更新服务配置。根据约定,当你发送一个挂起信号(信号1或HUP)时,大多数服务器进程(所有常用的进程)都会进行复位操作并重新加载它们的配置文件。


 如果按照上面这个“常规”的用法理解,咱们的设置并没有问题!但是,FPM就是那么“隔路”!!!所以,要看一个命令是否符合自己的预期,一定要进行测试或者使用官方提供的方式。

115.png

 
从上面线上服务器php-fpm.conf的配置项中可以看到,fpm配置了static模式,并且指定了50个children数,每个worker处理的最大请求数是2048(至于为何要进行重启,这是一种自我保护和修复的机制,就像是路由器,每天闲时自动重启一遍,会运行的更加稳定)。正是这50个(可能更少,最多50)worker,支撑了3点之后这段时间内的50*2048(最多,会少于这些)个请求。直至所有worker全部“死掉”之后,线上服务出现了问题。
 
四、问题总结:
 
  针对此次线上问题,应该总结:
  1. 关键业务节点完善报警机制
  2. 运维方面,nginx要健全健康检查
  3. 所有的脚本,使用官方提供的源码;网上找的脚本要进行测试
  4. 关键业务,增加机器
  5. 出问题先摘掉机器,以便于排查问题原因

 
五、扩展:
 
  关于fpm如何处理请求,可以参考文章《php-fpm解读-进程管理的三种模式》:http://www.jianshu.com/p/c9a028c834ff
 
六、其他:
 
fpm服务重启:/etc/init.d/php-fpm start/stop/restart
php-fpm执行kill下列命令后的结果: 
55566.png


-HUP会杀死进程
此时再去启动php-fpm服务时,报错端口被占用
 

-USR2顺利重新启动服务(更换了PID)
-USR1未做任何操作(PID未更新)
 
 
SIGTERM
程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理。通常用来要求程序自己正常退出,shell命令kill缺省产生这个信号。如果进程终止不了,我们才会尝试SIGKILL。
参考文档:http://blog.csdn.net/qq646232041/article/details/45642103
 

0 个评论

要回复文章请先登录注册