一个批量导入的接口,同步调用了第三方接口,今天出现了大批量超时问题,查看php-fpm日志
#php-fpm.log
[25-Sep-2019 08:53:55] WARNING: [pool www] child 3578, script '/home/www/app.test.me/public/index.php' (request: "POST /admin/order/import") execution timed out (115.225346 sec), terminating
[25-Sep-2019 08:53:55] WARNING: [pool www] child 3578 exited on signal 15 (SIGTERM) after 6193200.630314 seconds from start
[25-Sep-2019 08:53:55] NOTICE: [pool www] child 31629 started
查看nginx和php的配置
#nginx.conf
fastcgi_read_timeout 300
#php-fpm.conf
request_terminate_timeout=100
#php.ini
max_execution_time=0 //不限制
分析原因是php-fpm执行超时,使用测试脚本分析改进
样例1
脚本
#test.php
<?php
sleep(10)
配置
#nginx.conf
fastcgi_read_timeout 10
#php-fpm.conf
request_terminate_timeout=0 //不限制
浏览器 10 秒后返回 504 Gateway Time-out
#nginx-error.log
upstream timed out (110: Connection timed out) while reading response header from upstream
样例2
脚本
#test.php
<?php
sleep(10)
配置
#nginx.conf
fastcgi_read_timeout 10
#php-fpm.conf
request_terminate_timeout=5
浏览器 5 秒后返回 502 Bad Gateway
#nginx-error.log
recv() failed (104: Connection reset by peer) while reading response header from upstream
#php-fpm.log
[pool www] child 38629, script '/home/www/app.test.com/public/test.php' (request: "GET /test.php") execution timed out (5.392643 sec), terminating
样例3
脚本
#test.php
<?php
set_time_limit(1);
while(true){}
配置
#nginx.conf
fastcgi_read_timeout 10
#php-fpm.conf
request_terminate_timeout=5
浏览器返回 500 Internal Server Error
#php-fpm.log
[25-Sep-2019 20:50:51] PHP Fatal error: Maximum execution time of 1 second exceeded in /home/www/app.test.com/public/test.php on line 3
php.ini中的max_execution_time值 php-fpm.conf中的request_terminate_timeout值
这两项都是用来配置PHP脚本的最大执行时间。超时时php-fpm会终止脚本的执行,同时还会终止执行脚本的Worker进程。
文章开头 php-fpm child 3578被terminate后重新生成了新的Worker进程31629,所以nginx发现与自己通信的连接断了,就自然会返回502错误给客户端。客户端需再次发起请求重新建立新的连接,表象是刷新下浏览器即重新发起请求
适当调大 php-fpm.conf中的request_terminate_timeout,让PHP脚本不会因为执行时间长而被终止从而与nginx激活连接丢失。
request_terminate_timeout优先级高于max_execution_time,不想改全局的php.ini,只改php-fpm的配置就可以了。
网友评论