Heim >Backend-Entwicklung >PHP-Tutorial >Eine kurze Analyse mehrerer Timeout-Konfigurationen in PHP-Konfigurationsdateien
In diesem Artikel geht es um PHP-Konfigurationsdateien und die Analyse mehrerer Timeout-bezogener Konfigurationen in den Konfigurationsdateien (php.ini und php-fpm.conf). Ich hoffe, er kann Ihnen helfen!
Es gibt viele Timeout-bezogene Konfigurationen in php.ini und php-fpm.conf. Was genau bewirken diese Konfigurationen? Wie ist es im Quellcode implementiert? In diesem Artikel geht es um die folgenden Timeout-Konfigurationen:
Laufumgebung: Mac 10.14.2 + PHP 7.3.7
Das Parsen von php.ini wird in der Phase php_module_startup()
abgeschlossen, ini_entry befindet sich in main Die in .c
definierten Parsing-Regeln für jede php.ini-Konfiguration haben das folgende Format: 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)PHP definiert viele Makros für verschiedene Arten von Konfigurationen,
ZEND_INI_ENTRY3_EX
ist das Endergebnis danach Sie sind erweiterte Makros, wie zum Beispiel das PHP_INI_ENTRY
-Makro // 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)
Name:
KonfigurationsnameStandardwert:
Konfigurationsstandardwertmodifizierbar:
Konfigurationsbereich, der eingestellt werden kannDiese Modi legen fest, wann, wo und ob ein PHP-Befehl gesetzt werden kann. Jede Anweisung im Handbuch hat einen Modus, zu dem sie gehört. Beispielsweise können einige Befehle in PHP-Skripten mit ini_set() festgelegt werden, während andere nur in php.ini oder httpd.conf festgelegt werden können.Zum Beispiel gehört der Befehl „output_buffering“ zu PHP_INI_PERDIR und kann daher nicht mit ini_set() festgelegt werden. Aber die display_errors-Direktive gehört zu PHP_INI_ALL
und kann überall gesetzt werden, einschließlich ini_set().义 Modusbedeutet
PHP_INI_PERDIR Php_ini_user PHP_INI_SYSTEM kann in php.ini, .htaccess oder httpd.conf eingestellt werden PHP_INI_ALL kann in php.ini oder httpd eingestellt werden .conf Kann überall eingestellt werden on_modify: 配置修改函数
三、max_input_time、max_execution_time
因为
max_input_time
和max_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
。
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进程接收到
SIGINT
、SIGTERM
、SIGQUIT
、SIGUSR2
这些信号时,会调用fpm_pctl()
来进行处理。首先master进程会根据 接收到的信号 和 当前fpm的运行状态 来决定发送给worker进程的是
SIGQUIT
还是SIGTERM
信号,同时注册时间为process_control_timeout
的定时事件。如果在
process_control_timeout
时间内子进程没有退出,那么master进程会升级SIGQUIT
为SIGTERM
,SIGTERM
为SIGKILL
,并注册1s的定时事件。SIGKILL
就直接终止worker进程了,SIGTERM
还能再给worker进程1s的时间。综上,
process_control_timeout
可以理解为master进程留给worker进程结束自己的时间,要是到时间worker还没搞定那就开始master自己的策略了。五、request_terminate_timeout、request_slowlog_timeout
因为
request_terminate_timeout
和request_slowlog_timeout
联系比较密切,所以放在一起来讲。php-fpm.conf Erläuterung
request_terminate_timeout
; Das Zeitlimit für die Bearbeitung einer einzelnen Anfrage
; Diese Option sollte verwendet werden, wenn die INI-Option „max_execution_time“ nicht gestoppt wird Ausführung aus irgendeinem Grund. Ein Wert von „0“ bedeutet „aus“.
; Verfügbare Einheiten: Sekunden (Standard), Stunden (Stunden) oder Tage (Tage) ;
Übersetzung: Der Timeout-Zeitraum für die Ausführung einer Anfrage, nach dem der Arbeitsprozess beendet wird. Diese Option sollte verwendet werden, wenn die INI-Optionmax_execution_time
aus irgendeinem Grund die Skriptausführung nicht stoppen kann.request_slowlog_timeout
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_timeout
和request_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进程,
; Die Zeitüberschreitung für die Bearbeitung einer einzelnen Anfragekill(child_pid, SIGTERM);
; Ein Wert von „0s“ bedeutet „aus“.; (Standard), m(inutes), h(ours) oder d(ays); Standardwert: 0
🎜Übersetzung: Der Timeout-Zeitraum für die Ausführung einer Anfrage, nach dem ein PHP-Backtrace in die Slowlog-Datei ausgegeben wird. 🎜🎜Analysis🎜🎜request_slowlog_timeout
undrequest_terminate_timeout
werden bei der Heartbeat-Erkennung des Master-Prozesses (fpm_pctl_heartbeat()
) verwendet die Heartbeat-Zeitheartbeat Der vereinfachte Algorithmus ist 🎜🎜Die dritte Regel besteht darin, sicherzustellen, dass Slowlog keine Auswirkungen auf normale Anfragen hat,
- 🎜Wenn
request_terminate_timeout
aktiviert ist:request_terminate_timeout/ 1000*3
🎜- 🎜Wenn
🎜request_terminate_timeout
nicht aktiviert ist:request_slowlog_timeout/1000*3
oder 0🎜request_terminate_timeout >= request_slowlog_timeout
🎜heartbeat
dauert Die Zeitüberschreitung sollte 1/3 der Zeit betragen, um eine zu häufige Heartbeat-Erkennung zu vermeiden, da jede Heartbeat-Erkennung alle Arbeitsprozesse durchlaufen muss. 🎜🎜Wenn ein Timeout-Ereignis auftritt, wird der Arbeitsprozess direkt beendet,kill(child_pid, SIGTERM);
, und dann recycelt der Kernel Ressourcen und schließt den client_socket, und nginx gibt einen 502-Fehler zurück zum Browser. 🎜🎜Empfohlenes Lernen: „🎜PHP-Video-Tutorial🎜“🎜
Das obige ist der detaillierte Inhalt vonEine kurze Analyse mehrerer Timeout-Konfigurationen in PHP-Konfigurationsdateien. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!