淺析PHP配置檔案中的幾種逾時配置

青灯夜游
發布: 2023-04-10 22:16:01
轉載
5490 人瀏覽過

這篇文章帶大家聊聊PHP設定文件,解析一下設定檔(php.ini 和 php-fpm.conf)中的幾個超時相關的配置,希望能夠給大家提供幫助!

淺析PHP配置檔案中的幾種逾時配置

一、摘要

php.ini 和 php-fpm.conf 中有很多逾時相關的配置,那麼這些配置到底有什麼作用呢?在原始碼中又是怎麼實現的呢?這篇文章就來講講下面幾種逾時配置:

php.ini
  • #max_execution_time
  • max_input_time
php- fpm.conf
  • process_control_timeout
  • #process_control_timeout

#process_control_timeout

#process_control_timeout

request_terminate_timeout

request_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: 設定的可被設定範圍PHP_INI_PERDIR,因而不能用 ini_set() 來設定。但 display_errors 指令是屬於 PHP_INI_ALL 因而就可以在任何地方被設定,包括 ini_set()。 模式意義##可在使用者腳本(例如ini_set())或Windows 註冊表(自PHP 5.3 起)以及.user.ini 中設定
這些模式決定著一個PHP 的指令在何時何土地,是否能夠被設定。手冊中的每個指令都有其所屬的模式。例如有些指令可以在 PHP 腳本中用 ini_set() 來設定,而有些則只能在 php.ini 或 httpd.conf 中。 例如 output_buffering 指令是屬於
PHP_INI_USER
#########PHP_INI_PERDIR## #######可在php.ini,.htaccess 或httpd.conf 中設定###############PHP_INI_SYSTEM#########可在php .ini 或httpd.conf 中設定###############PHP_INI_ALL#########可在任何地方設定########## ##

on_modify: 配置修改函数

三、max_input_time、max_execution_time

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

php.ini 解释

max_input_time

; Maximum amount of time each script may spend parsing request data. It's a good
; idea to limit this time on productions servers in order to eliminate unexpectedly
; long running scripts.
; Note: This directive is hardcoded to -1 for the CLI SAPI
; http://php.net/max-input-time

翻译过来就是:max_input_time是每个脚本可以花在解析请求数据上的最大时间。在生产服务器上通过限制max_input_time可以清除掉长时间运行的脚本。在CLI模式下会硬编码为-1,即无限制。

max_execution_time

; Maximum execution time of each script, in seconds
; http://php.net/max-execution-...
; Note: This directive is hardcoded to 0 for the CLI SAPI

翻译:max_execution_time是每个脚本的最大可执行时间。在CLI模式下硬编码为0

配置解析规则

// 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,修改函数为OnUpdateTimeout
PHP_INI_ENTRY("max_execution_time", "30",    PHP_INI_ALL, OnUpdateTimeout)
登入後複製

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

// main.c
static 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.c
int 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
淺析PHP配置檔案中的幾種逾時配置

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 解释

; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds

翻译:process_control_timeout是留给子进程处理来自master进程信号的时间限制。

分析

当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_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

#翻譯:執行一個請求的超時時間,在這之後worker進程將被終止。這個選項應該被用在max_execution_time 這個ini選項因為某些原因不能停止腳本執行的時候。

request_slowlog_timeout

##; The timeout for serving a single request after which a PHP backtrace will be

; dumped to the 'slowlog' file. A value of '0s' means 'off' .
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0

翻譯:執行一個請求的超時時間,在這之後一個PHP的backtrace會被輸出到slowlog檔案裡。

分析

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中文網其他相關文章!

相關標籤:
來源:segmentfault.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板