一次nginx 504 Gateway Time-out錯誤排查、解決記錄,經過反覆檢查,發現造成這個問題的原因就是PHP的CURL沒有設定逾時時間,解決辦法只要設定逾時時間或者修改一下nginx的配置即可解決。
記一次莫名其妙的網站失去響應排查。之前網站一直是使用nginx做代理後端的apache運行php來提供服務。apache經常會不定期不定時間的出現不能服務失去響應,然後nginx出現"504 Gateway Time-out"
查看錯誤記錄檔也看不到任何東西,以為是apache的bug(其實不是,下面會說原因)。
也許年齡大了人就不愛折騰,願意保持原狀不動,使用監控工具,每次收到警示後都重新啟動apache勉強維持著。終於有一天我煩了,不就是處理php嗎,我不用apache總行了吧,一怒之下使用源安裝php-fpm轉移到php-fpm來運行php。安裝php並不麻煩,使用源安裝還是很順利的,唯一需要做的就是設定php worker背景工作處理序的日誌輸出php錯誤記錄檔。
一切準備就緒後把原來的proxy_pass換成fastcgipass就可以了。
upstream apachephp {
server www.jb51.net:8080; #Apache1
}
....
proxy_pass http://apachephp;
替換成成
upstream php {
server 127.0.0.1:9000;
}
...
fastcgi_pass php;
就可以把apache上跑的php遷移到php-fpm上來跑。
原以為這樣就可以高枕無憂了,遷移完成是也確實沒什麼問題,但是如果你不去分析問題的根本原因在哪。問題還是會找上門來,第二天nginx又報了504的gateway timeout。這回沒apache什麼事了吧,apache總算撇清了關係。
那應該還是在nginx和php-fpm身上,查看nginx的錯誤記錄檔,可以看到
[error] 6695#0: *168438 upstream timed out (110: Connection timed out) while reading response header from upstream,
...
request: "GET /kd/open.php?company=chinapost&number=PA24977020344 HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "www.jb51.net"
看到這裡基本上就排除了nginx嫌疑,nginx是在等待php處理"GET /kd/open.php?company=chinapost&number=PA24977020344 HTTP/1.1"逾時退出了。
馬上重啟php-fpm,問題沒有了,網站可以訪問了。
再次訪問該頁面,依然沒有響應,但同時訪問別的頁面正常,該頁面重新整理幾次後,整個網站都是bad gateway timeout了。
問題就縮小到這個php指令碼上了。
netstat -napo |grep "php5-fpm" | wc -l
查看php背景工作處理序已經達到了設定檔裡的上限10,有種感覺就是大家都被open.php這個指令碼卡住了。
這個指令碼是幹什麼的呢?這個指令碼就是採集快遞資訊的,裡面用到了php_curl。
PHP指令碼如果執行時間超過php.ini中的配置項max_execution_time不出結果就會強制退出。
查看了php.ini中max_execution_time確實配了,值為30。
萬能google派上用場了,經過不斷google後得到下面這句話
set_time_limit()函數和配置指令max_execution_time隻影響指令碼本身執行的時間。任何發生在諸如使用system()的系統調用,流操作,資料庫操作等的指令碼執行的最大時間不包括其中,當該指令碼已運行。www.jbxue.com
就是說如果指令碼中執行了其它操作的時間是不計在指令碼已耗用時間當中的,如果你沒設定逾時,那麼php就會一直等待調用的結果。
查看open.php源檔案一看,果然沒有設定curl的逾時時間。
增加如下兩行,重新重新整理,後問題解決了。
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); //timeout on connect
curl_setopt($ch, CURLOPT_TIMEOUT, 10); //timeout on response
當然,除了這種方法外,php-fpm裡也提供參數供我們強制殺死長時間無結果的進程,只是該參數預設沒開啟。
php-fpm的設定檔裡可以設定一個參數request_terminate_timeout,請求終止的逾時時間,當請求執行超過這個時間就會被kill。
同時它還有個參數request_slowlog_timeout,用來記錄慢請求日誌的。
命令列運行php的話,可以使用這段代碼
$real_execution_time_limit = 60; //時間限制if (pcntl_fork()){// some long time code which should be// terminated after $real_execution_time_limit seconds passed if it's not// finished by that time}else{sleep($real_execution_time_limit);posix_kill(posix_getppid(), SIGKILL);}
http://www.bkjia.com/PHPjc/776506.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/776506.htmlTechArticle一次nginx 504 Gateway Time-out錯誤排查、解決記錄,經過反覆檢查,發現造成這個問題的原因就是PHP的CURL沒有設定逾時時間,解決辦法只要設定逾時...