我們的一個web項目,由于新上城市增多,導致訪問量增大,DB壓力增大,作為提供接口的業務方,最近被下游反饋大量請求“502”。
502,bad gateway,一般都是upstream(這里就是php)出錯,對于php,造成502的原因常見的就是腳本執行超過timeout設置時間,或者timeout設置過大,導致php進程長時間不能被釋放,沒有空閑worker進程來接客。
我們的項目就是php執行時間設置過短導致的,對于這種情況,可以先適當增大php的執行時間,先保證清除502,優化的事情畢竟要花更多的時間。
控制php執行時間的選項有兩個,在php.ini中 max_execution_time 和php-fpm中 request_terminate_timeout,其中 request_terminate_timeout 可以覆蓋 max_execution_time,所以如果不想改全局的php.ini,那只改php-fpm的配置就可以了。
下邊我就來詳細的分析一下為什么php腳本執行超出設置時間會導致nginx返回502。
先來布景,讓問題復現:
nginx和php分別只啟動一個worker,方便追蹤。
php-fpm的request_terminate_timeout設置為3S。
測試腳本test.php
sleep(20);echo 'ok';
go go go:
在瀏覽器訪問www.v.com/test.php,3S后如期出現...404???what???
出師不利啊,趕緊看看nginx的配置文件
這個location配置是當發生5xx錯誤時跳轉到一個好看點的界面,但是我在/usr/share/nginx/html下并沒有50x.html這個文件。所以搞了個404出來。這不是很影響我判斷問題的準確性?直接注釋掉!再次訪問,等待3S,終于'正常'的界面出來了。
環境好了,下邊就上套路,按照web問題的排查套路走一遍,先看看錯誤日志吧:
nginx:
報錯都是 recv() failed (104: Connection reset by peer。
recv時失敗了,連接被重置了。為啥連接被重置了?難道一言不合。
我們在看看php-fpm的錯誤日志:
(注意php-fpm中php_admin_value[error_log]選項指定php的錯誤日志,會覆蓋php.ini中的。但是這里不是看php的錯誤,而是看php-fpm的錯誤。php-fpm的錯誤日志由php-fpm.conf中的error_log選項指定。)
每一次請求都是產生2個WARNING和1個NOTICE:
WARNING:腳本執行超時了,終止了。
WARNING:子進程收到SIGTERM信號退出了。
NOTICE:啟了一個新的子進程(因為我設置的pm.min_spare_servers = 1)
新聞熱點
疑難解答