一次nginx 504 Gateway Time-out錯(cuò)誤排查、解決記錄
記一次莫名其妙的網(wǎng)站失去響應(yīng)排查。之前網(wǎng)站一直是使用nginx做代理后端的apache運(yùn)行php來(lái)提供服務(wù)。apache經(jīng)常會(huì)不定期不定時(shí)間的出現(xiàn)不能服務(wù)失去響應(yīng),然后nginx出現(xiàn)"504 Gateway Time-out"
查看錯(cuò)誤日志也看不到任何東西,以為是apache的bug(其實(shí)不是,下面會(huì)說(shuō)原因)。
也許年齡大了人就不愛(ài)折騰,愿意保持原狀不動(dòng),使用監(jiān)控工具,每次收到報(bào)警后都重新啟動(dòng)apache勉強(qiáng)維持著。終于有一天我煩了,不就是處理php嗎,我不用apache總行了吧,一怒之下使用源安裝php-fpm轉(zhuǎn)移到php-fpm來(lái)運(yùn)行php。安裝php并不麻煩,使用源安裝還是很順利的,唯一需要做的就是設(shè)置php worker工作進(jìn)程的日志輸出php錯(cuò)誤日志。
一切準(zhǔn)備就緒后把原來(lái)的proxy_pass換成fastcgipass就可以了。
upstream apachephp {
server www.dhdzp.com:8080; #Apache1
}
....
proxy_pass http://apachephp;
替換成成
upstream php {
server 127.0.0.1:9000;
}
...
fastcgi_pass php;
就可以把a(bǔ)pache上跑的php遷移到php-fpm上來(lái)跑。
原以為這樣就可以高枕無(wú)憂了,遷移完成是也確實(shí)沒(méi)什么問(wèn)題,但是如果你不去分析問(wèn)題的根本原因在哪。問(wèn)題還是會(huì)找上門(mén)來(lái),第二天nginx又報(bào)了504的gateway timeout。這回沒(méi)apache什么事了吧,apache總算撇清了關(guān)系。
那應(yīng)該還是在nginx和php-fpm身上,查看nginx的錯(cuò)誤日志,可以看到
[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.dhdzp.com"
看到這里基本上就排除了nginx嫌疑,nginx是在等待php處理"GET /kd/open.php?company=chinapost&number=PA24977020344 HTTP/1.1"超時(shí)退出了。
馬上重啟php-fpm,問(wèn)題沒(méi)有了,網(wǎng)站可以訪問(wèn)了。
再次訪問(wèn)該頁(yè)面,依然沒(méi)有響應(yīng),但同時(shí)訪問(wèn)別的頁(yè)面正常,該頁(yè)面刷新幾次后,整個(gè)網(wǎng)站都是bad gateway timeout了。
問(wèn)題就縮小到這個(gè)php腳本上了。
netstat -napo |grep "php5-fpm" | wc -l
查看php工作進(jìn)程已經(jīng)達(dá)到了配置文件里的上限10,有種感覺(jué)就是大家都被open.php這個(gè)腳本卡住了。
這個(gè)腳本是干什么的呢?這個(gè)腳本就是采集快遞信息的,里面用到了php_curl。
PHP腳本如果執(zhí)行時(shí)間超過(guò)php.ini中的配置項(xiàng)max_execution_time不出結(jié)果就會(huì)強(qiáng)制退出。
查看了php.ini中max_execution_time確實(shí)配了,值為30。
萬(wàn)能google派上用場(chǎng)了,經(jīng)過(guò)不斷google后得到下面這句話
set_time_limit()函數(shù)和配置指令max_execution_time只影響腳本本身執(zhí)行的時(shí)間。任何發(fā)生在諸如使用system()的系統(tǒng)調(diào)用,流操作,數(shù)據(jù)庫(kù)操作等的腳本執(zhí)行的最大時(shí)間不包括其中,當(dāng)該腳本已運(yùn)行。
就是說(shuō)如果腳本中執(zhí)行了其它操作的時(shí)間是不計(jì)在腳本運(yùn)行時(shí)間當(dāng)中的,如果你沒(méi)設(shè)置超時(shí),那么php就會(huì)一直等待調(diào)用的結(jié)果。
查看open.php源文件一看,果然沒(méi)有設(shè)置curl的超時(shí)時(shí)間。
增加如下兩行,重新刷新,后問(wèn)題解決了。
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); //timeout on connect
curl_setopt($ch, CURLOPT_TIMEOUT, 10); //timeout on response
當(dāng)然,除了這種方法外,php-fpm里也提供參數(shù)供我們強(qiáng)制殺死長(zhǎng)時(shí)間無(wú)結(jié)果的進(jìn)程,只是該參數(shù)默認(rèn)沒(méi)打開(kāi)。
php-fpm的配置文件里可以設(shè)置一個(gè)參數(shù)request_terminate_timeout,請(qǐng)求終止的超時(shí)時(shí)間,當(dāng)請(qǐng)求執(zhí)行超過(guò)這個(gè)時(shí)間就會(huì)被kill。
同時(shí)它還有個(gè)參數(shù)request_slowlog_timeout,用來(lái)記錄慢請(qǐng)求日志的。
命令行運(yùn)行php的話,可以使用這段代碼
$real_execution_time_limit = 60; //時(shí)間限制
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);
}
相關(guān)文章
Nginx負(fù)載均衡/SSL配置的實(shí)現(xiàn)
這篇文章主要介紹了Nginx負(fù)載均衡/SSL配置的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
Nginx服務(wù)器屏蔽與禁止屏蔽網(wǎng)絡(luò)爬蟲(chóng)的方法
今天小編就為大家分享一篇關(guān)于Nginx服務(wù)器屏蔽與禁止屏蔽網(wǎng)絡(luò)爬蟲(chóng)的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03
Nginx正則表達(dá)式相關(guān)的參數(shù)和規(guī)則介紹
這篇文章主要給大家介紹了關(guān)于Nginx正則表達(dá)式相關(guān)的參數(shù)和規(guī)則的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Nginx正則表達(dá)式具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
nginx使用stream模塊代理端口的實(shí)現(xiàn)
本文主要介紹了nginx使用stream模塊代理端口,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02
分享nginx+php-fpm實(shí)現(xiàn)大文件下載排坑的過(guò)程
這篇文章主要介紹了nginx+php-fpm實(shí)現(xiàn)大文件下載排坑的過(guò)程,文中通過(guò)代碼實(shí)例相結(jié)合的形式給大家介紹的非常詳細(xì),具有一定得參考借鑒價(jià)值,需要的朋友參考下吧2018-08-08

