前置條件: 適用於常規請求都沒問題,但是執行某些php腳本需要超過一分鐘的情況下的502/504,並不是任何請求都502/504的情況(這說明php-fpm或者nginx配置錯誤)。 出現502/504的原因 502 執行腳本時間太長,期間php沒有返回任何的數據。php-fpm超時,nginx沒超 ...
前置條件:
適用於常規請求都沒問題,但是執行某些php腳本需要超過一分鐘的情況下的502/504,並不是任何請求都502/504的情況(這說明php-fpm或者nginx配置錯誤)。
出現502/504的原因
502
執行腳本時間太長,期間php沒有返回任何的數據。php-fpm超時,nginx沒超時。nginx認為php-fpm罷工了,然後拋出了異常。
504
執行腳本時間太長,期間php沒有返回任何的數據。php-fpm沒超時,nginx超時。nginx認為php-fpm響應太慢,nginx沒憋住拋出了異常。
不生效的解決方案(防止各位師傅踩坑):
代碼
set_time_limit(0);
ignore_user_abort(true);
ini_set('max_execution_time', 600);
不生效原理剖析
以上代碼的作用設置了php代碼本身可以更長的時間處理任務並且不報致命錯誤,但不代表程式一定無限制的可以執行這麼久。因為Nginx與PHP進程通信方式是檢測到.php的文件交給php-fpm進程處理,php-fpm是一個fastcgi進程管理器,php-fpm一旦超時,php-fpm會強制終結掉這個進程,這就是報502的原因。
這段代碼又無法控制nginx fastcgi的一些機制,所以報504的原因。
意味著僅代碼層配置還不夠,伺服器也得配置。
官方文檔對這2個函數和1個配置的解釋:
##### set_time_limit:
Set the number of seconds a script is allowed to run. If this is reached, the script returns a fatal error. The default limit is 30 seconds or, if it exists, the max_execution_time value defined in the php.ini.
##### ignore_user_abort:
Set whether a client disconnect should abort script execution.When running PHP as a command line script, and the script's tty goes away without the script being terminated then the script will die the next time it tries to write anything, unless enable is set to true.
##### max_execution_time:
This sets the maximum time in seconds a script is allowed to run before it is terminated by the parser. This helps prevent poorly written scripts from tying up the server. The default setting is 30. When running PHP from the command line the default setting is 0.
On non Windows systems, the maximum execution time is not affected by system calls, stream operations etc. Please see the set_time_limit() function for more details.
**Your web server can have other timeout configurations that may also interrupt PHP execution..Apache has a Timeout directive and IIS has a CGI timeout function. Both default to 300 seconds. See your web server documentation for specific details.**
加粗字體意思是說:Web 伺服器可以有其它超時配置,這些配置也可能會中斷 PHP 執行。Apache 有一個 Timeout 指令,IIS 有一個 CGI 超時功能。 兩者都預設為 300 秒。(nginx也有一個fastcgi超時配置,預設60秒)。
502解決方案
再php-fpm.conf中添加request_terminate_timeout = 600即可,如下:
#編輯php-fpm配置
vim /usr/local/php/etc/php-fpm.conf
#添加此配置,單位預設為秒,多少秒請根據情況自行設定
request_terminate_timeout = 600
#保存後重啟
service php-fpm restart
504解決方案
再nginx配置中添加 fastcgi_connect_timeout 600; fastcgi_read_timeout 600; fastcgi_send_timeout 600; 即可,如下:
#編輯nginx某個站點的配置
vim /usr/local/nginx/conf/vhost/test.conf
#再location中添加以下配置,單位預設為秒,多少秒請根據情況自行設定,完整代碼塊如下:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include /usr/local/nginx/conf/fastcgi_params;
fastcgi_connect_timeout 600;
fastcgi_read_timeout 600;
fastcgi_send_timeout 600;
}
#保存後測試配置是否有問題,如果有問題,請修改好後再次嘗試。
../../sbin/nginx -t
#確認配置正常,重啟
service nginx restart
配置含義官方說明:
PHP-FPM:
request_terminate_timeout
The timeout for serving a single request after which the worker process will be killed. This option should be used when the 'max_execution_time' ini option does not stop script execution for some reason. A value of '0' means 'Off'. Available units: s(econds)(default), m(inutes), h(ours), or d(ays). Default value: 0.
Nginx:
fastcgi_connect_timeout 60s;
Defines a timeout for establishing a connection with a FastCGI server. It should be noted that this timeout cannot usually exceed 75 seconds.
fastcgi_read_timeout 60s;
Defines a timeout for reading a response from the FastCGI server. The timeout is set only between two successive read operations, not for the transmission of the whole response. If the FastCGI server does not transmit anything within this time, the connection is closed.
fastcgi_send_timeout 60s;
Sets a timeout for transmitting a request to the FastCGI server. The timeout is set only between two successive write operations, not for the transmission of the whole request. If the FastCGI server does not receive anything within this time, the connection is closed.