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 相关文章推荐
用Socket发送电子邮件
Oct 09 PHP
在PHP3中实现SESSION的功能(一)
Oct 09 PHP
从网上搜到的phpwind 0day的代码
Dec 07 PHP
把1316这个数表示成两个数的和,其中一个为13的倍数,另一个是11的倍数,求这两个数。
Jun 24 PHP
linux下为php添加curl扩展的方法
Jul 29 PHP
php获取ip的三个属性区别介绍(HTTP_X_FORWARDED_FOR,HTTP_VIA,REMOTE_ADDR)
Sep 23 PHP
PHP生成验证码时“图像因其本身有错无法显示”的解决方法
Aug 07 PHP
php常见的魔术方法详解
Dec 25 PHP
php使用pear_smtp发送邮件
Apr 15 PHP
Windows 下安装 swoole 图文教程(php)
Jun 05 PHP
PHP中十六进制颜色与RGB颜色值互转的方法
Mar 18 PHP
PHP 裁剪图片
Mar 09 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 前一天或后一天的日期
2008/06/28 PHP
tp5框架基于ajax实现异步删除图片的方法示例
2020/02/10 PHP
javascript 有趣而诡异的数组
2009/04/06 Javascript
iframe 父窗口和子窗口相互的调用方法集锦
2010/12/15 Javascript
javascript 二进制运算技巧解析
2012/11/27 Javascript
原生js实现半透明遮罩层效果具体代码
2013/06/06 Javascript
Js制作简单弹出层DIV在页面居中 中间显示遮罩的具体方法
2013/08/08 Javascript
仿百度输入框智能提示的js代码
2013/08/22 Javascript
JS关闭窗口或JS关闭页面的几种代码分享
2013/10/25 Javascript
js购物车实现思路及代码(个人感觉不错)
2013/12/23 Javascript
javascript异步编程的4种方法
2014/02/19 Javascript
JavaScript中Number.MIN_VALUE属性的使用示例
2015/06/04 Javascript
EasyUI加载完Html内容样式渲染完成后显示
2016/07/25 Javascript
jQuery实现页面点击后退弹出提示框的方法
2016/08/24 Javascript
原生JS简单实现ajax的方法示例
2016/11/29 Javascript
JS实现改变HTML上文字颜色和内容的方法
2016/12/30 Javascript
react.js 父子组件数据绑定实时通讯的示例代码
2017/09/25 Javascript
使用Vue.js和Flask来构建一个单页的App的示例
2018/03/21 Javascript
vue拖拽组件 vuedraggable API options实现盒子之间相互拖拽排序
2019/07/08 Javascript
聊聊Vue中provide/inject的应用详解
2019/11/10 Javascript
详解vue组件之间的通信
2020/08/30 Javascript
微信小程序实现点击导航条切换页面
2020/11/19 Javascript
详解在Python和IPython中使用Docker
2015/04/28 Python
Python开发微信公众平台的方法详解【基于weixin-knife】
2017/07/08 Python
程序员写Python时的5个坏习惯,你有几条?
2018/11/26 Python
分析运行中的 Python 进程详细解析
2019/06/22 Python
Tensorflow加载Vgg预训练模型操作
2020/05/26 Python
基于HTML5超酷摄像头(HTML5 webcam)拍照功能实现代码
2012/12/13 HTML / CSS
Puritan’s Pride(普丽普莱)官方网站:美国最大最全的保健品公司之一
2016/10/23 全球购物
Nike香港官网:Nike HK
2019/03/23 全球购物
学生夜不归宿检讨书
2014/09/23 职场文书
2014年财务部工作总结
2014/11/11 职场文书
大学生活委员竞选稿
2015/11/21 职场文书
2016年5月份红领巾广播稿
2015/12/21 职场文书
高中体育课教学反思
2016/02/16 职场文书
教师个人教学反思
2016/02/23 职场文书