由于http是基于tcp的,在tcp中,客户端中断了连接,服务端是无法感知的,只能通过发心跳包来检测,而显然我们的nginx是没有发心跳包的,所以,包括nginx,php-fpm都是不知道客户端已断开,而且web服务器也都没做这种中断机制,所以服务器依然会把客户端的请求走完,或者遇到某个超时设置才会停止执行。
测试代码:
在浏览器中访问
http://192.168.10.200/test.php
然后关掉这个请求
tail -f test-close.txt
可以看到,依然在不断写入,观察了5分钟,没有停下来的意思。
重启php-fpm就好了:service php-fpm restart
好了,没有再写入了。
突然想起一个问题,php.ini不是有超时时间设置吗,怎么没生效呢?
vi /etc/php.ini
看到如下:
; Maximum execution time of each script, in seconds
; http://php.net/max-execution-time
; Note: This directive is hardcoded to 0 for the CLI SAPI
max_execution_time = 30
而且phpinfo显示也是30s,说明php-fpm正确的加载了配置。
明明是有设置的,而且我使用的不是CLI模式
再看
php -i|grep max_execution_time
max_execution_time => 0 => 0
这里又是什么设置?是因为在CLI SAPI模式下max_execution_time会被强制设置0,我们不参考这个。
再来看官网对于max_execution_time的提示:
The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.
意思是 max_execution_time 计算的只是PHP脚本本身执行的时间,执行之外的时间都不会计算在内。哪些属于执行之外的时间呢?包含socket交互,系统调用(如sleep),系统操作等等。
设置 max_execution_time = 1
,重启php-fpm
代码改为
请求,关闭
程序1秒就终止了。
可见 max_execution_time 是生效的,只是之前sleep的系统调用一次次截断了执行时间而已,然后执行时间就变得很长了。
那么如何控制一个请求总的请求时间呢,即使你使用了sleep?
php-fpm的配置里也有请求处理时间的设置,意思就是当max_execution_time没生效时,这个超时会起作用。
vi /etc/php-fpm.d/www.conf
可以看到
; 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 = 0
这里没有设置,我来设置一下
request_terminate_timeout = 60
测试
1、重新请求,关闭,观察写入情况,发现写入一些之后就没有写了,时间短了很多。
2、CLI下 php test.php 观察十分钟也没停。ctrl+c关掉就好了。
在window的phpstudy测试,代码一样,一请求就关闭
结果是,严格按照php.ini配置的max_execution_time的秒数来执行的!!!
nginx的超时设置
keepalive_timeout 65; 该参数用于设置客户端连接保持会话的超时时间,超过这个时间服务器会关闭该连接