PHP实现服务端主动断开连接后继续执行任务
很多时候,对于前端的接口请求,我们只想执行“一半”的脚本,并不想后端完全执行完毕后再返回给前端,这样会给客户端带来不好的体验是响应太慢,这时候我们可以考虑一种做法,主动断开客户端的请求。
可以利用的是ignore_user_abort($boolen)这个函数。正常来说,在http请求中,服务端每次的输出缓冲池满了后便会触发客户端输出,这时候php会去检测当前的请求状态,如果状态正常,脚本继续运行,如果状态异常,则中断当前php脚本的运行。而ignore_user_abort($boolen)这个函数,如果$boolen值设置为true时,php会忽略连接的异常状态,把脚本执行到完。这里介绍一下php内部对于连接处理的三种状态。
0 - NORMAL(正常)
1 - ABORTED(异常退出)
2 - TIMEOUT(超时)
当 PHP 脚本正常地运行 NORMAL 状态时,连接为有效。当远程客户端中断连接时,ABORTED 状态的标记将会被打开。远程客户端连接的中断通常是由用户点击 STOP 按钮导致的。当连接时间超过 PHP 的时限(请参阅set_time_limit() 函数)时,TIMEOUT 状态的标记将被打开。
脚本中,这三种状态值可以通过connection_status()函数来获取,而注意了,其实php中并不是每次的输出都会自动去检测这个值,而是只有当输出缓冲池满了后才会去触发(同理,浏览器收到请求时也不会立刻输出在页面上,而是缓冲池满了才会输出,这种措施有利于提高系统效率)。这里插个外话,我们可以为程序注册一个关闭函数,register_shutdown_function(),通过这个注册函数,当php异常退出,或者超时时都会触发关闭函数,这样我们可以执行一些任务来追踪http状态码是499或502,或者执行一些任务来处理这些异常请求。
关于连接处理的详细可以看这里:http://php.net/manual/zh/features.connection-handling.php
下面回到正文,既然知道了如果保持会话连接了,那如何主动断开http请求?答案很简单,利用header()函数既可以了。
header(“Content-Length:XXX”):Content-Length的作用:浏览器接收到指定Content-Length大小的消息实体后,则会断开与服务器的连接。
header(“Connection: Close”):Connection的作用:浏览器接收到Connection的Close或Keep-Alive后,决定是关闭连接还是继续使用当前的连接进下一次请求。
有关Content-Length,这里又得偏离话题介绍一个知识点,关于ob。
这是一个程序例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $a = ''; $size = 0; set_time_limit(0); ob_implicit_flush(true); ignore_user_abort (true); $json = "{'t':'xxx','dd':'xxxx'}"; echo $json; $size=ob_get_length(); header("Content-Length: $size"); header("Connection: close"); header("HTTP/1.1 200 OK"); ob_flush(); sleep(5); file_put_contents('.\client_test.txt', $json); |
这个例子里面有几个注意的点:
1、执行任务时记得带上set_time_limit(0),否则后端可能会执行不完。
2、header()函数执行,输出http表头前,脚本不可以有任何输出,否者会有报错,因此这里要利用ob来做缓冲。
下篇文章分析客户端主动断开后服务端是否还会继续运行任务。