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