>首页> IT >

浅析PHP配置文件中的几种超时配置

时间:2022-03-09 11:53:06       来源:转载
本篇文章带大家聊聊PHP配置文件,解析一下配置文件(php.ini 和 php-fpm.conf)中的几种超时相关的配置,希望能够给大家提供帮助!

一、概要

php.ini 和 php-fpm.conf 中有很多超时相关的配置,那么这些配置到底有什么作用呢?在源码中又是怎么实现的呢?这篇文章就来讲讲下面几种超时配置:

php.ini
max_execution_timemax_input_time
php-fpm.conf
process_control_timeoutrequest_terminate_timeoutrequest_slowlog_timeout

运行环境:Mac 10.14.2 + PHP 7.3.7

二、配置解析规则

解析规则

php.ini的解析是在php_module_startup()阶段完成,ini_entry是在 main.c中为每个php.ini配置定义的解析规则,格式如下:

ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, arg1, arg2, arg3, displayer)

PHP为不同类型的配置定义了很多宏,ZEND_INI_ENTRY3_EX是它们展开后的最终宏,比如PHP_INI_ENTRY

PHP_INI_ENTRY(name, default_value, modifiable, on_modify)

参数解释

name:配置名称

default_value:配置默认值

modifiable:配置的可被设定范围

on_modify:配置修改函数

三、max_input_time、max_execution_time

因为max_input_timemax_execution_time联系比较密切,所以放在一起来讲。

php.ini 解释

配置解析规则

// max_input_time,默认值为无限制STD_PHP_INI_ENTRY("max_input_time", "-1",    PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, max_input_time, php_core_globals, core_globals)  // max_execution_time,默认值为30s,修改函数为OnUpdateTimeoutPHP_INI_ENTRY("max_execution_time", "30",    PHP_INI_ALL, OnUpdateTimeout)

OnUpdateTimeout()函数如下,由第二节可知配置解析发生在php_module_startup()阶段,此时EG(timeout_seconds)被赋值为了max_execution_time,但还没有设置定时器。

// main.cstatic PHP_INI_MH(OnUpdateTimeout){    if (stage==PHP_INI_STAGE_STARTUP) {        /* Don"t set a timeout on startup, only per-request */    /* EG(timeout_seconds) = max_execution_time */        ZEND_ATOL(EG(timeout_seconds), ZSTR_VAL(new_value));        return SUCCESS;    }    zend_unset_timeout();    ZEND_ATOL(EG(timeout_seconds), ZSTR_VAL(new_value));    zend_set_timeout(EG(timeout_seconds), 0);    return SUCCESS;}

设置超时定时器

// main.cint php_request_startup(void) {  ......  if (PG(max_input_time) == -1) {    zend_set_timeout(EG(timeout_seconds), 1);  } else {  zend_set_timeout(PG(max_input_time), 1);  }  ......}int php_execute_script(zend_file_handle *primary_file){  ......    if (PG(max_input_time) != -1) {    zend_set_timeout(INI_INT("max_execution_time"), 0);  }    ......}

从上面代码可以看到,如果设置了max_input_time(即值不等于-1,-1可以认为是在CLI模式下),在php_request_startup()阶段会设置一个定时器,超时时间为max_input_time;在php_execute_script()阶段会重新设置一个定时器,超时时间为max_execution_time。那么整个PHP脚本执行的最大执行时间就等于max_input_time+ max_execution_time

如果没有设置max_input_time的话(即值等于-1),在php_request_startup()阶段也会设置一个定时器,但超时时间被设为了EG(timeout_seconds),而EG(timeout_seconds)已经在php_module_startup()阶段被赋值为max_execution_time,所以此时的超时时间就是max_execution_time;在php_execute_script()阶段不会重新设置定时器,前一阶段设置的max_execution_time定时器仍然生效着。那么整个PHP脚本的最大执行时间就是max_execution_time

zend_set_time()使用setitimer(ITIMER_PROF, &t_r, NULL);来实现定时器,ITIMER_PROF会统计包括用户态和内核态下所花费的时间,而像sleep()这样的系统调用会让进程挂起,不占用cpu时间片,所以这俩超时时间是不包括sleep()时间的。

当定时器到时间后,ZendVM会抛出E_ERROR,即Fatal error错误。

四、process_control_timeout

php-fpm.conf 解释

分析

当master进程接收到SIGINTSIGTERMSIGQUITSIGUSR2这些信号时,会调用fpm_pctl()来进行处理。

首先master进程会根据 接收到的信号 和 当前fpm的运行状态 来决定发送给worker进程的是SIGQUIT还是SIGTERM信号,同时注册时间为process_control_timeout的定时事件。

如果在process_control_timeout时间内子进程没有退出,那么master进程会升级SIGQUITSIGTERMSIGTERMSIGKILL,并注册1s的定时事件。SIGKILL就直接终止worker进程了,SIGTERM还能再给worker进程1s的时间。

综上,process_control_timeout可以理解为master进程留给worker进程结束自己的时间,要是到时间worker还没搞定那就开始master自己的策略了。

五、request_terminate_timeout、request_slowlog_timeout

因为request_terminate_timeoutrequest_slowlog_timeout联系比较密切,所以放在一起来讲。

php-fpm.conf 解释

分析

request_slowlog_timeoutrequest_terminate_timeout 用在master进程的心跳检测中(fpm_pctl_heartbeat()),心跳时间heartbeat简化后的算法是

在开启request_terminate_timeout情况下:request_terminate_timeout/1000*3

在未开启request_terminate_timeout情况下:request_slowlog_timeout/1000*3或者 0

request_terminate_timeout >= request_slowlog_timeout

第三条规则是为了保证slowlog不影响到正常的请求,heartbeat取超时时间的1/3应该是为了避免心跳检测过于频繁,因为每次心跳检测都需要遍历所有worker进程。

如果超时事件发生了,那么将直接kill掉worker进程,kill(child_pid, SIGTERM);,之后内核回收资源关闭client_socket,nginx返回502错误给浏览器。

推荐学习:《PHP视频教程》

以上就是浅析PHP配置文件中的几种超时配置的详细内容,更多请关注php中文网其它相关文章!

关键词: 配置文件 执行时间 相关文章