php-fpm超时时间设置request_terminate_timeout资源问题分析


Posted in PHP onSeptember 27, 2019

php日志中有一条超时的日志,但是我request_terminate_timeout中设置的是0,理论上应该没有超时时间才对。

PHP Fatal error: Maximum execution time of 30 seconds exceeded in ...

OK,先列出现在的配置:

php-fpm:
request_terminate_timeout = 0
php.ini:
max_execution_time = 30

先查阅了一下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

这个注释说明了,request_terminate_timeout 适用于,当max_execution_time由于某种原因无法终止脚本的时候,会把这个php-fpm请求干掉。

再看看max_execution_time的注释:这设置了脚本被解析器中止之前允许的最大执行时间,默认是30s。看样子,我这个请求应该是被max_execution_time这个设置干掉了。

好吧,不死心,做了一个实验:

php-fpm request_terminate_timeout 设置 0 15
php.ini max_execution_time 设置 30 30
执行结果 php有Fatal error超时日志,http状态码为500 php无Fatal error超时日志,http状态码为502,php-fpm日志中有杀掉子进程日志

好吧,结论是web请求php执行时间受到2方面控制,一个是php.ini的max_execution_time(要注意的是sleep,http请求等待响应的时间是不算的,这里算的是真正的执行时间),另一个是php-fpm request_terminate_timeout 设置,这个算的是请求开始n秒。

request_terminate_timeout引起的资源问题

request_terminate_timeout的值如果设置为0或者过长的时间,可能会引起file_get_contents的资源问题。
如果file_get_contents请求的远程资源如果反应过慢,file_get_contents就会一直卡在那里不会超时。我们知道php.ini 里面max_execution_time 可以设置 PHP 脚本的最大执行时间,但是,在 php-cgi(php-fpm) 中,该参数不会起效。

真正能够控制 PHP 脚本最大执行时间的是 php-fpm.conf 配置文件中的request_terminate_timeout参数。
request_terminate_timeout默认值为 0 秒,也就是说,PHP 脚本会一直执行下去。
这样,当所有的 php-cgi 进程都卡在 file_get_contents() 函数时,这台 Nginx+PHP 的 WebServer 已经无法再处理新的 PHP 请求了,

Nginx 将给用户返回“502 Bad Gateway”。修改该参数,设置一个 PHP 脚本最大执行时间是必要的,
但是,治标不治本。例如改成 30s,如果发生 file_get_contents() 获取网页内容较慢的情况,这就意味着 150 个 php-cgi 进程,每秒钟只能处理 5 个请求,WebServer 同样很难避免”502 Bad Gateway”。

解决办法是:request_terminate_timeout设置为10s或者一个合理的值,
或者给file_get_contents加一个超时参数。

$ctx = stream_context_create(array(
  'http' => array(
    'timeout' => 10  //设置一个超时时间,单位为秒
  )
));
 
file_get_contents($str, 0, $ctx);

php-fpm中的request_terminate_timeout最好不要设置

刚转到php-fpm没几天就发现,进入我的joomla后台,firefox偶尔会给我白屏的那种http 503,这种情况仅出现在天翼云的服务器上,而我在国外的同样配置的服务器一点问题都没有,后来发现是request_terminate_timeout的问题。

每次登陆joomla后台,joomla都会去检查是否有更新(检查成功后cache,默认保存该cache 6小时),而且分为joomla主程序和joomla扩展两个部分,如下图:

php-fpm超时时间设置request_terminate_timeout资源问题分析

不出意外的话,服务器会发起两个php进程,分别分配给两个php-fpm children,去连接joomla的官方update服务器。好,问题就来了,我的request_terminate_timeout = 30s,30秒不完成则超时,参见天翼云主机的国际出口相当蛋疼!没错,30秒内,天翼云主机根本无法完成连接joomla更新服务器并检查是否有更新这整个过程。这也很好解释了为什么同样配置的国外服务器就没有问题,因为它们完成上述更细过程仅需要在2~5秒左右。

我的apache超时设置是30秒,php.ini中最长执行时间野是30秒,多年来都没有任何问题,没有30秒还打不开的网页,所以我就没多想给php-fpm的request_terminate_timeout = 30s。经过这次的事情发现此30秒非鄙30秒啊……

php-fpm设置request_terminate_timeout后,php.ini中的max_execution_time和max_input_time都会失效,以php-fpm中的设置为准;
apache+mod_php在timeout后,只会在日志中记录一下,仅此而已。php-fpm中的request_terminate_timeout超时之后,日志中记录http 503的同时,最要命的,它还会直接杀死造成这个http 503的php-fpm child,并生成新的child。
在我的joomla更新这个实例中,就会有两个php-fpm children同时被杀死。而我的天翼云主机是低配,只有一个cpu核心,我也只启动了两个php-fpm children,两个同时死了,我的firefox这边也就http 503 Service Unavailable的白屏了。php-fpm的error_log如下:

[27-Sep-2014 10:41:06] WARNING: [pool www] child 1882, script '/home/onepx/public_html/administrator/index.php' (request: "POST /administrator/index.php") execution timed out (30.004534 sec), terminating
[27-Sep-2014 10:41:06] WARNING: [pool www] child 1882 exited on signal 15 (SIGTERM) after 164.717323 seconds from start

[27-Sep-2014 10:41:06] NOTICE: [pool www] child 1886 started
[27-Sep-2014 10:41:06] WARNING: [pool www] child 1883, script '/home/onepx/public_html/administrator/index.php' (request: "POST /administrator/index.php") execution timed out (30.005201 sec), terminating
[27-Sep-2014 10:41:06] WARNING: [pool www] child 1883 exited on signal 15 (SIGTERM) after 166.718162 seconds from start
[27-Sep-2014 10:41:06] NOTICE: [pool www] child 1887 started

像joomla这种全php的网站,每个连接都需要apache+php-fpm协同运作。即便php-fpm中的request_terminate_timeout时间设置很长,apache中的timeout时间设置略短,只要apache的timeout到了,php-fpm照样在后面杀进程……
如果网站的访问者比较多,php-fpm的child是被许多访问者共用的,杀一个child,就有可能导致几个用户同时http 503 Service Unavailable。所以,我的建议是——php-fpm中的request_terminate_timeout最好不要设置,只给apache一个timeout就够了。

PHP 相关文章推荐
编译问题
Oct 09 PHP
php&java(三)
Oct 09 PHP
PHP的FTP学习(四)
Oct 09 PHP
PHP 伪静态隐藏传递参数名的四种方法
Feb 22 PHP
PhpMyAdmin出现export.php Missing parameter: what /export_type错误解决方法
Aug 09 PHP
php中inlcude()性能对比详解
Sep 16 PHP
php中getservbyport与getservbyname函数用法实例
Nov 18 PHP
CI映射(加载)数据到view层的方法
Mar 28 PHP
PHP读取文件的常见几种方法
Nov 03 PHP
Django 标签筛选的实现代码(一对多、多对多)
Sep 05 PHP
ThinkPHP框架结合Ajax实现用户名校验功能示例
Jul 03 PHP
Laravel 前端资源配置教程
Oct 18 PHP
thinkPHP+LayUI 流加载实现功能
Sep 27 #PHP
PHP的cookie与session原理及用法详解
Sep 27 #PHP
PHP下载文件函数与用法示例
Sep 27 #PHP
PHP的JSON封装、转变及输出操作示例
Sep 27 #PHP
php面向对象重点知识分享
Sep 27 #PHP
php中关于换行的实例写法
Sep 26 #PHP
php伪静态验证码不显示的解决方案
Sep 26 #PHP
You might like
php实现分页显示
2015/11/03 PHP
JS操作XML中DTD介绍及使用方法分析
2019/07/04 PHP
php在linux环境中如何使用redis详解
2020/12/15 PHP
TNC vs BOOM BO3 第一场2.13
2021/03/10 DOTA
javascript 复杂的嵌套环境中输出单引号和双引号
2009/05/26 Javascript
Jquery Ajax学习实例7 Ajax所有过程事件分析示例
2010/03/23 Javascript
利用location.hash实现跨域iframe自适应
2010/05/04 Javascript
Js组件的一些写法
2010/09/10 Javascript
Javascript操作URL函数修改版
2013/11/07 Javascript
如何判断Javascript对象是否存在的简单实例
2016/05/18 Javascript
深入理解jQuery 事件处理
2016/06/14 Javascript
jquery radio的取值_radio的选中_radio的重置方法
2016/09/20 Javascript
jQuery+CSS3实现仿花瓣网固定顶部位置带悬浮效果的导航菜单
2016/09/21 Javascript
微信小程序 天气预报开发实例代码源码
2017/01/20 Javascript
微信小程序 按钮滑动的实现方法
2017/09/27 Javascript
详解vue-cli项目开发/生产环境代理实现跨域请求
2019/07/23 Javascript
微信JSSDK实现打开摄像头拍照再将相片保存到服务器
2019/11/15 Javascript
JavaScript浅层克隆与深度克隆示例详解
2020/09/01 Javascript
jQuery实现放大镜案例
2020/10/19 jQuery
Javascript 模拟mvc实现点餐程序案例详解
2020/12/24 Javascript
Python日期操作学习笔记
2008/10/07 Python
python黑魔法之编码转换
2016/01/25 Python
Python时间戳使用和相互转换详解
2017/12/11 Python
Python简单处理坐标排序问题示例
2019/07/11 Python
python opencv pytesseract 验证码识别的实现
2020/08/28 Python
selenium3.0+python之环境搭建的方法步骤
2021/02/01 Python
HTML5 Web Workers之网站也能多线程的实现
2013/04/24 HTML / CSS
cosme官方海外旗舰店:日本最大化妆品和美容产品的综合口碑网站
2017/01/18 全球购物
aden + anais官方网站:婴儿襁褓、毯子、尿布和服装
2017/06/21 全球购物
澳大利亚设计的婴儿和女孩的衣服:Oobi
2018/12/16 全球购物
Yahoo-PHP面试题4
2012/05/05 面试题
就业表自我评价分享
2014/02/06 职场文书
机械制造专业毕业生求职信
2014/03/02 职场文书
基层党员学习党的群众路线教育实践活动心得体会
2014/11/04 职场文书
趣味运动会加油词
2015/07/18 职场文书
磁贴还没死, 微软Win11可修改注册表找回Win10开始菜单
2021/11/21 数码科技