NGINX + PHP-FPM 502

NGINX + PHP-FPM 报 502 错误,我想大部分 SA 都遇到过吧。
根据报错的频率,能够分为两种状况,间歇性的502和连续性的502。
这里只讨论第一种状况——间歇性的502。 php

502,是后端 PHP-FPM 不可用形成的,间歇性的502通常认为是因为 PHP-FPM 进程重启形成的。 nginx

在 PHP-FPM 的配置中存在这么一项: shell

How much requests each process should execute before respawn.
Useful to work around memory leaks in 3rd party libraries.
For endless request processing please specify 0
Equivalent to PHP_FCGI_MAX_REQUESTS
<value name=”max_requests”>500</value> 后端

这段配置的意思是,当一个 PHP-CGI 进程处理的请求数累积到 500 个后,自动重启该进程。 bash

可是为何要重启进程呢? 服务器

通常在项目中,咱们多多少少都会用到一些 PHP 的第三方库,这些第三方库常常存在内存泄漏问题,若是不按期重启 PHP-CGI 进程,势必形成内存使用量不断增加。所以 PHP-FPM 做为 PHP-CGI 的管理器,提供了这么一项监控功能,对请求达到指定次数的 PHP-CGI 进程进行重启,保证内存使用量不增加。 并发

正是由于这个机制,在高并发的站点中,常常致使 502 错误,我猜想缘由是 PHP-FPM 对从 NGINX 过来的请求队列没处理好。不过我目前用的仍是 PHP 5.3.2,不知道在 PHP 5.3.3 中是否还存在这个问题。 less

目前咱们的解决方法是,把这个值尽可能设置大些,尽量减小 PHP-CGI 从新 SPAWN 的次数,同时也能提升整体性能。在咱们本身实际的生产环境中发现,内存泄漏并不明显,所以咱们将这个值设置得很是大(204800)。你们要根据本身的实际状况设置这个值,不能盲目地加大。 curl

1 首先查看一下目前php-fpm的进程数量 高并发

ps aux |grep php-fpm |grep -v grep |grep "^www"|wc -l

将输出结果与nginx.conf配置文件中的max_children参数作对比

若是两个值相近,那么就须要将max_children相应的增长

2 看一下nginx.conf配置文件中Nginx的等待时间的设置,能够相应增长

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;

后来我将网站上一个shell脚本作了相应的修改:

主要是检测php-fpm进程的

脚本原则:
在检测到502报错以后,在干掉php-fpm进程以前先弄清楚一些东西:
统计子进程的数量是为了,判断一下是否是由于子进程的数量接近配置文件中max_children这个值的设置
若是这两个值很接近的话,说明排队的php请求比较多,处理请求过于繁忙也会致使502报错
统计CPU使用率最大的php-fpm进程所占用的CPU%,并记录相应的进程号,能够追踪进程号,作初步肯定是不是 file_get_contents() 致使的问题
总之这些操做是有助于分析事发缘由的
另外,若是killall进程以后不检测是否将进程杀干净,有可能会影响进程的从新启动,因此有必要进行这一步判断
若是运行该脚本的机器是在线服务器,那么当检测到进程没有杀干净时,最好报警或者是记录日志,尽可能避免一直杀进程的操做


脚本内容:

#!/bin/bash
funCheck()
{
if [ -z "`ps aux |grep php-fpm |grep -v grep`" ];then
       if [ -z "`cat /usr/local/php/php-fpm.pid `" ];then 
       echo "php-fpm process doesn't exist ,you can start it now `date`" >> $Log
  else
    echo "php-fpm process  exists still  `date`" >> $Log  
  fi
fi
}


Log=/home/sysadmin/zhaoyj/log/PhpFpm.log
ChildProcess=`ps aux |grep php-fpm |grep -v grep |grep "^www"|wc -l`
DATE=`date "+%Y%m%d-%H:%M:%S"`
Message="MG Server php-fpm child process number is $ChildProcess at $DATE"
Admin="邮件地址"
if [ -e /var/lock/subsys/502 ]
then
 if [ $ChildProcess -ge 100 ];then 
   echo "$Message" |mail -s "$Message" $Admin
   echo "$Message" >> $Log
 fi

Record=``ps aux |grep php-fpm|grep -v grep |awk '{print $3"\t"$2"\t"$11}'|tr -d :|sort -nr|head -1` CPU=`awk '{print $1}' $Record` PID=`awk '{print $2}' $Record` Result=`awk -v NUM1=$CPU -v NUM2=50 'BEGIN{print(NUM1>NUM2)?"1":"0"}'` Message2="php-fpm child process CPU% is $Result"    if [ $Result -eq 0 ];then       echo "$Message2 ,normal now $DATE" >> $Log     else        echo "$Message2 ,not normal now $DATE" >> $Log        echo "$Message2 ,not normal now $DATE" |mail -s "$Message2 ,not normal now $DATE" $Admin    fi  killall -9 curl 2>/dev/null  killall -9 php-fpm 2>/dev/null  funCheck  service php-fpm start >/dev/null  echo "[ `date +'%h %d %T'` ] PHP-FPM died with no response, all processes restarted">>/usr/local/php/log/php-fpm-restart.log else     touch /var/lock/subsys/502     if [ `curl --connect-timeout 5 -I URL 2>/dev/null | grep '502 Bad Gateway' -c` != '0' ]     then         killall -9 php-fpm 2>/dev/null   funCheck         service php-fpm start >/dev/null         echo "[ `date +'%h %d %T'` ] PHP-FPM died with 502 bad gateway, all processes restarted">>/usr/local/php/log/php-fpm-restart.log     fi     rm -f /var/lock/subsys/502 fi

相关文章
相关标签/搜索