说明:

LNMP架构。

crontab里有每隔20分钟重启php的任务;然后我用python写了个每1分钟检测php-cgi进程是否存在的脚本,如果不存在则调用重启php的脚本,并邮件通知管理员。crontab 和python脚本都调用的是/usr/local/webserver/php/restart_php.sh 这个脚本,权限都是root。
根据如下的邮件通知截图,说明在 13:20 和 14:20 的时候,crontab 里执行重启php任务失败(此时站点表现为502 Bad Gateway,因为 nginx 找不到反向代理)。接着后一分钟 python 脚本检测到 php-cgi 监听 9000 端口的进程不存在,然后再次调用了 restart_php.sh 脚本。
 
我们去看一下 php 的日志(/uar/local/webserver/php/log/php-fpm.log),为什么 crontab 重启会失败。
SIGCHLD信号说明:
“任何一个子进程(init除外)在exit后并非马上就消失,而是留下一个称为僵尸进程的数据结构,等待父进程处理。这是每个子进程都必需经历的阶段。另外子进程退出的时候会向其父进程发送一个SIGCHLD信号。”
然而父进程并没有挂起等待子进程的完全结束,所以会出现什么情况?我们先看一下restart_php.sh:
 
 
php-fpm stop命令会给 php-cgi 子进程发送SIGTERM信号,为确认所有进程被终止,紧接着又调用了两次 killall,然后才执行 php-fpm start 命令。但是这时候所有的子进程也不一定都终止了,所以如果这时候 php-fpm start,由于子进程还没有释放绑定的端口(9000),就会出现端口绑定失败:
注意看日志,在端口绑定失败之后,还陆续有子进程退出的日志打印,再次说明 php-fpm start 的时候还有子进程没 kill 干净。
 
再看 13:21 的时候,python 脚本又来调用 restart_php.sh 了:
注意看有4个子进程只运行了59秒(对比前面的日志,正常运行的子进程应该是1200秒——20分钟),这就是13:20重启的时候生成的4个子进程。(如果重启正常应该是75个子进程,因为端口绑定失败,所以其他子进程没启动成功)
然后这次重启就成功了。为什么这次重启一定会成功?因为第二次重启在第一次重启一分钟后,如果第一次重启成功了,第二次重启不会进行;第一次重启失败了(会产生4个子进程),那么第二次重启时会首先杀掉前面的4个子进程,因为只有4个,kill 起来很快很干净,然后再执行 php-fpm start 时就不会端口绑定错误了。
 
解决办法
知道原因之后,解决方案就简单了。目的只有一个:在php-fpm start 之前确保子进程已经完全退出。
(1)使用 killall -w 参数
但是要注意。
(2)使用 ps 、pgrep 等命令检测php-cgi子进程是否存在。
(3)在php-fpm start 之前 sleep 几秒。
 
我采用的是方案(1),目前测试中,尚未出现问题。从下面日志中可见php-fpm start 距离 php-fpm 完全退出约有两秒的时间。
 
 

 
另外,从下面日志看出,502 Bad Gateway 这个问题在2015年很少,从2016年2月22号开始,很频繁出现9000端口绑定错误。不知道是改动了什么地方。
 
 
 
 
再另外,重启php的根本原因是句柄泄漏(越来越多文件打开,不重启会导致系统死机)?这个问题似乎由来已久,在/home/bbs/目录下有一个php_file_open.txt文件,创建日期为12年7月30号。
 
文件内容为 lsof -c php-cgi 命令的执行结果:
 
这个文件有17000多行,可见当时就存在句柄泄漏的问题,所以才有了crontab里的定时重启php。

BBS 502 BadGateway 原因分析的更多相关文章

  1. 网站假死 重启NGINX无效 必须重启PHP 原因分析

    一.错误提示说明: Nginx 502 Bad Gateway:请求的PHP-CGI已经执行,但是由于某种原因(一般是读取资源的问题)没有执行完毕而导致PHP-CGI进程终止. Nginx 504 G ...

  2. SELECT TOP 1 比不加TOP 1 慢的原因分析以及SELECT TOP 1语句执行计划预估原理

    本文出处:http://www.cnblogs.com/wy123/p/6082338.html 现实中遇到过到这么一种情况: 在某些特殊场景下:进行查询的时候,加了TOP 1比不加TOP 1要慢(而 ...

  3. mysql索引无效且sending data耗时巨大原因分析

    一朋友最近新上线一个项目,本地测试环境跑得好好的,部署到线上却慢得像蜗牛一样.后来查询了一下发现一个sql执行了16秒,有些长的甚至80秒.本地运行都是毫秒级别的查询.下面记录一下困扰了两天的,其中一 ...

  4. 网站用域名能访问,用域名IP不能访问的原因分析

    原因分析:一般虚拟主机是不能直接输入IP进行访问的 因为一个IP下有很多网站 ,只能用域名进行访问.如果想IP也能访问,必须网站有独立的IP地址,不是共享IP.如果是IIS的话,要把主机头对应的域名去 ...

  5. JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法

    今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时 ...

  6. 在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案

    转自:http://www.jianshu.com/p/89687f618837 原因分析   当我们在Android依赖库中使用switch-case语句访问资源ID时会报如下图所示的错误,报的错误 ...

  7. uboot使用tftp下载时出现“checksum bad”问题原因分析

    一.问题 二.原因分析 你的虚拟机是不是这样设置的呢? 如果是的话,请看下边的解释: 使用NAT模式,就是让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网.也就是说,使用NA ...

  8. Activity内部Handler引起内存泄露的原因分析

    有时在Activity中使用Handler时会提示一个内存泄漏的警告,代码通常如下: public class MainActivity extends Activity { private Text ...

  9. Beforeunload打点丢失原因分析及解决方案

    淘宝的鱼相在 2012 年 8 月份发表了一篇文章,里面讲述了他们通过一个月的数据采集试验,得到的结果是:如果在浏览器的本页面刷新之前发送打点请求,各浏览器都有不同程度的点击丢失情况,具体点击丢失率统 ...

随机推荐

  1. 数据库连接不上的原因以及springBoot的ioc无法自动注入

    无法自动注入解决了,数据池的连接还有问题: 错误原因1: :数据库用的是Mysql8版本,以前的配置mysql驱动包却是5.1.37版本.只需修改驱动包为8.0.11版本即可. <!-- mys ...

  2. 【学习笔记】【Javaweb】二、Session对象过期时间三种设置方法、Session失效监听器

    一.前言 本文:https://www.cnblogs.com/Twobox/p/10361712.html 参考:https://www.cnblogs.com/diewufeixian/p/422 ...

  3. SQL Server 关于 Table 字典数据的查询SQL

    分享一个关于查询SQL Server Table 结构的SQL 语句. T-SQL 如下: SELECT (case when a.colorder=1 then d.name else '' end ...

  4. Prometheus Operator - 每天5分钟玩转 Docker 容器技术(177)

    前面我们介绍了 Kubernetes 的两种监控方案 Weave Scope 和 Heapster,它们主要的监控对象是 Node 和 Pod.这些数据对 Kubernetes 运维人员是必须的,但还 ...

  5. Server 2008 R2多用户远程桌面连接授权,解决120天过期问题

    在工作中,我们往往需要远程服务器,经常会遇到以下这两个麻烦事. 一.远程桌面的连接数限制,超出系统就会提示超过连接数. 二.远程桌面连接时,同一个用户不能同时远程2个桌面连接. ----------- ...

  6. Python爬虫之正则表达式(2)

    # 最常规的匹配 import re content = 'Hello 123 4567 World_This is a Regex Demo' print(len(content)) result ...

  7. June. 24th 2018, Week 26th. Sunday

    Beautiful things don't ask for attention. 真正美丽的东西,并不会刻意寻求别人的注目. From The Secret Life of Walter Mitty ...

  8. Github: 从github上拉取别人的源码,并推送到自己的github仓库

    比如说,将 https://github.com/lizhenliang/tomcat-java-demo 迁移到 https://github.com/lousia001/tomcat-java-d ...

  9. Linux定是调用shell脚本删除文件

    编写脚本 vi delbak.sh 代码如下: #!/bin/sh location="/home/mysql/backup/" find $location -mtime +7 ...

  10. pdf 下载demo

    最近写了个pdf下载的demo,在这里记录一下.. 1  要下载pdf首先要有pdf 模板 ,制作pdf 模板就是 word 另存为 pdf . 2 用 Adobe Acrobat X Pro 这个软 ...