nginx和php-fpm連接超時的那點事

現(xiàn)在線上系統(tǒng)的架構大致是這樣的,除去cache的proxy機器外,還有項目的nginx proxy機器,后面跟nginx webserver + php-fpm。有時候,會看到proxy nginx的日志里面會有各種異常狀態(tài)碼,比如499,502,504等,這些是什么情況導致的呢?最近一一測試了下。

架構示意

 nginx proxy => nginx webserver => php-fpm

狀態(tài)碼說明

499:客戶端(或者proxy)主動斷開連接
502:網(wǎng)關錯誤(Bad Gateway)
504:網(wǎng)關超時:(Gateway Timeout)

1 proxy和webserver不能連接

1.1 proxy_pass ip不存在

這時候會重復發(fā)送arp解析協(xié)議,約3秒后超時,proxy返回碼為502。

1.2 proxy_pass ip存在

1)webserver機器上端口上沒有對應服務。

webserver所在機器的內核會直接返回RESET包,沒有額外超時,proxy返回碼為502

2)webserver機器端口上有服務,但是iptables DROP了proxy的包

因為webserver drop(iptables -I INPUT -s xxx.xxx.xxx.xxx -j DROP)了proxy的包,proxy會TCP連接不斷重試,默認會重試60秒后proxy返回碼504,這個重試時間60秒由參數(shù) proxy_connect_timeout指定,重試間隔就是TCP的重試間隔(1,2,4...)。

如果在超時之前,客戶端主動關閉連接(比如停止瀏覽器的請求),這個時候proxy會記錄 499狀態(tài)碼,而且$request_time 記錄的是proxy已經處理的時間,而$upstream_response_time- ??蛻舳酥鲃雨P閉后,proxy也不會再向webserver發(fā)送重試請求。

但是如果你在proxy配置了proxy_ignore_client_abort on;,那么即便客戶端主動關閉,proxy還是會不停的發(fā)送重試請求到webserver,直至超時,記錄的狀態(tài)碼為webserver返回的狀態(tài)碼。

3) webserver機器端口有服務,但是iptables REJECT了proxy的包

因為webserver reject(iptables -I INPUT -s xxx.xxx.xxx.xxx -j REJECT)了proxy的包,與drop不同之處在于,這個時候webserver會返回一個端口不可達的ICMP包給proxy,proxy會重試一次后返回 502 給客戶端,超時時間約為1秒。

2 proxy和webserver連接正常(請求時間過長)

proxy的nginx.conf中的proxy_read_timeout=60
webserver的nginx.conf中fastcgi_read_timeout=300
php-fpm中的 request_terminate_timeout=120

2.1 php執(zhí)行時間超過proxy的proxy_read_timeout

假設php-fpm有一個test.php執(zhí)行時間為100秒,超過了默認的proxy_read_timeout=60;,則到1分鐘后proxy會關閉到webserver的連接,webserver記錄的返回碼為499,proxy的返回碼為 504,客戶端看到的返回碼也就是 504

關于proxy_read_timeout要多說一句,在nginx文檔中可以看到這個參數(shù)的含義是

The timeout is set only between two successive read operations,
 not for the transmission of the whole response.

意思是這個超時不是整個response的傳輸超時,而是兩次讀操作之間的間隔超時。比如在proxy中設置proxy_read_timeout=10,而測試的 test.php 如下:

<?php
sleep(7);
echo "haha\n";
ob_flush();
flush();
sleep(7);
echo "haha after 7s\n";
?>

這整個請求的響應時間是14秒,其實是不會超時的,因為相鄰兩次讀操作的間隔是7秒小于10秒。注意代碼中的ob_flush()flush()兩個函數(shù),其中ob_flush()是為了刷php的緩存,而flush()則是為了刷系統(tǒng)層面的緩存。當然如果你將 /etc/php5/fpm/php.ini中設置output_buffering=off,則可以不用調用ob_flush()了,但是flush()還是需要的。如果不flush的話,php會等到整個響應完成才會將數(shù)據(jù)返回給webserver,webserver再返回給proxy,在沒有返回整個響應之前(14秒才能返回),超過了 proxy_read_timeout的10秒,此時,proxy會關閉和webserver的連接,導致出現(xiàn)504錯誤。 為了這個測試test.php不超時,webserver的nginx還要加一個配置 fastcgi_buffering off;,因為雖然我們的php返回了數(shù)據(jù)了,但是webserver的nginx還是緩存了fastcgi的返回,導致沒有及時將數(shù)據(jù)返回給proxy,從而超時。

在如上面配置好后,可以發(fā)現(xiàn),瀏覽器輸出了haha\nhaha after 7s。問題來了,這兩個字符串是同時輸出的,并沒有像代碼中那樣隔了7秒,那這個問題是什么導致的呢?想必你應該知道了,proxy的nginx也有緩存配置,需要關閉才能看到先后輸出兩個字符串的效果。nginx proxy的緩存配置為proxy_buffering off;,這樣你就能看到先后輸出兩個字符串的效果了。

2.2 php執(zhí)行時間超過webserver的fastcgi_read_timeout

設置fastcgi_read_timeout=10,test.php執(zhí)行時間100秒,則10秒后webserver會關閉和PHP的連接,webserver記錄日志的返回碼為 504,proxy日志的返回碼也是 504。

2.3 php執(zhí)行時間超過php-fpm的request_terminate_timeout

設置request_terminate_timeout=5,test.php還是執(zhí)行100秒,可以發(fā)現(xiàn)5秒之后,php-fpm會終止對應的php子進程,webserver日志的狀態(tài)碼為 404,proxy的日志的狀態(tài)碼也是 404。

注:經測試,在php-fpm模式中,php.ini中的max_execution_time參數(shù)沒有什么效果。

3 關于文件數(shù)問題

Linux里面的一些限制參數(shù)可以通過 ulimit -a查看。比如我的debian8.2系統(tǒng)的輸出如下:

# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 96537
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1000000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 96537
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

其中open files是一個進程可以同時打開的文件數(shù),超過了這個數(shù)會報too many open files錯誤,修改open files可以通過 ulimit -n xxx實現(xiàn)。而max user processes則是用戶最多創(chuàng)建的進程數(shù)。

另外,系統(tǒng)允許打開的最大文件數(shù)在配置file-max中。

# cat /proc/sys/fs/file-max
2471221

要修改file-max,可以通過

# sysctl -w fs.file-max=1000000

用永久生效,需要在/etc/sysctl.conf中加入這行

fs.file-max=1000000

然后sysctl -p即可生效。

要針對用戶限制文件數(shù)之類的,可以修改/etc/security/limits.conf,內容格式如下:

<domain>        <type>  <item>  <value>

## 比如限制 bob這個用戶的一個進程同時打開的文件數(shù)
## Example hard limit for max opened files
bob        hard nofile 4096
## Example soft limit for max opened files
bob        soft nofile 1024

nginx配置中的worker_rlimit_nofile可以配置為open files這個值。

參考資料

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375

推薦閱讀更多精彩內容

  • Nginx簡介 解決基于進程模型產生的C10K問題,請求時即使無狀態(tài)連接如web服務都無法達到并發(fā)響應量級一萬的現(xiàn)...
    魏鎮(zhèn)坪閱讀 2,026評論 0 9
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,807評論 18 139
  • 上一篇《WEB請求處理一:瀏覽器請求發(fā)起處理》,我們講述了瀏覽器端請求發(fā)起過程,通過DNS域名解析服務器IP,并建...
    七寸知架構閱讀 81,118評論 21 356
  • 《老男孩Linux運維》筆記 隱藏Nginx軟件版本號 一般來說,軟件的漏洞都和版本有關。因此要盡量隱藏對訪問用戶...
    Zhang21閱讀 3,667評論 0 28
  • 海邊的Smile閱讀 175評論 9 1