在使用Nginx時,常常會碰到 502 Bad Gateway
和 504 Gateway Time-out
錯誤,下面以 Nginx+PHP-FPM 來分析下這兩種常見錯誤的緣由和解決方案。php
在 php.ini
和 php-fpm.conf
中分別有這樣兩個配置項:max_execution_time
和 request_terminate_timeout
。服務器
這兩項都是用來配置一個 PHP 腳本的最大執行時間的。當超過這個時間時,PHP-FPM不僅會終止腳本的執行,還會終止執行腳本的Worker進程。因此Nginx會發現與本身通訊的鏈接斷掉了,就會返回給客戶端502錯誤。php-fpm
以PHP-FPM的 request_terminate_timeout=30
秒時爲例,報 502 Bad Gateway 錯誤的具體信息以下:unix
1)Nginx錯誤訪問日誌:日誌
2013/09/19 01:09:00 [error] 27600#0: *78887 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 192.168.1.101, server: test.com, request: "POST /index.php HTTP/1.1", upstream: "fastcgi://unix:/dev/shm/php-fcgi.sock:", host: "test.com", referrer: "http://test.com/index.php"
2)PHP-FPM報錯日誌:code
WARNING: child 25708 exited on signal 15 (SIGTERM) after 21008.883410 seconds from start
因此只需將這兩項的值調大一些就可讓PHP腳本不會由於執行時間長而被終止了。request_terminate_timeout
能夠覆蓋 max_execution_time
,因此若是不想改全局的php.ini,那隻改PHP-FPM的配置就能夠了。server
此外要注意的是Nginx的upstream模塊中的 max_fail
和 fail_timeout
兩項。有時Nginx與上游服務器(如Tomcat、FastCGI)的通訊只是偶然斷掉了,但 max_fail
若是設置的比較小的話,那麼在接下來的 fail_timeout
時間內,Nginx都會認爲上游服務器掛掉了,都會返回502錯誤。
因此能夠將 max_fail
調大一些,將 fail_timeout
調小一些。進程
PHP-FPM設置的腳本最大執行時間已經夠長了,但執行耗時PHP腳本時,發現Nginx報錯從502變爲504了。這是爲何呢?ip
由於咱們修改的只是PHP的配置,Nginx中也有關於與上游服務器通訊超時時間的配置factcgi_connect/read/send_timeout
。it
以Nginx超時時間爲90秒,PHP-FPM超時時間爲300秒爲例,報504 Gateway Timeout錯誤時的Nginx錯誤訪問日誌以下:
2013/09/19 00:55:51 [error] 27600#0: *78877 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.1.101, server: test.com, request: "POST /index.php HTTP/1.1", upstream: "fastcgi://unix:/dev/shm/php-fcgi.sock:", host: "test.com", referrer: "http://test.com/index.php"
調高這三項的值(主要是read和send兩項,默認不配置的話Nginx會將超時時間設爲60秒)以後,504錯誤也解決了。
並且這三項配置能夠配置在http、server級別,也能夠配置在location級別。擔憂影響其餘應用的話,就配置在本身應用的location中吧。
要注意的是 factcgi_connect/read/send_timeout
是對 FastCGI 生效的,而 proxy_connect/read/send_timeout
是對 proxy_pass
生效的。
配置舉例:
location ~ \.php$ { root /home/cdai/test.com; include fastcgi_params; fastcgi_connect_timeout 180; fastcgi_read_timeout 600; fastcgi_send_timeout 600; fastcgi_pass unix:/dev/shm/php-fcgi.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /home/cdai/test.com$fastcgi_script_name; }