在实际项目中常常会有这样的需求,对于前端发过来的请求,须要在后端进行长时间的处理,但为了让使用者有更好的体验,为了让PHP在后端处理长时间任务时不阻塞,快速响应页面请求,所以在这里对fastcgi_finish_request的应用进行总结概括。固然php实现非阻塞的方式有不少种,好比异步脚本、swoole,但我的认为fastcgi_finish_request最为简单方便。php
(PHP 5 >= 5.3.3, PHP 7)html
fastcgi_finish_request — 冲刷(flush)全部响应的数据给客户端前端
boolean fastcgi_finish_request ( void )
此函数冲刷(flush)全部响应的数据给客户端并结束请求。 这使得客户端结束链接后,须要大量时间运行的任务可以继续运行。后端
成功时返回 TRUE, 或者在失败时返回 FALSE服务器
echo "program start..."; file_put_contents('/tmp/garylog.log','start-time:'.date('Y-m-d H:i:s')."\n", FILE_APPEND); fastcgi_finish_request();sleep(1); // set_time_limit(0); // sleep(150); $num = 25; $num += 1; sleep(5); echo 'debug...'; file_put_contents('/tmp/garylog.log', 'start-proceed:'.$num.',时间'.date('Y-m-d H:i:s')."\n", FILE_APPEND); sleep(10); file_put_contents('/tmp/garylog.log', 'end-time:'.date('Y-m-d H:i:s')."\n", FILE_APPEND);
运行测试swoole
从代码的可移植性讲的话, 能够在代码中附上以下代码:并发
if (!function_exists("fastcgi_finish_request")) { function fastcgi_finish_request() { } }
不会形成代码部署在非fpm环境下形成问题.异步
对于上面说到的问题:在高并发下执行时间太久也会致使fastcgi进程不够用,不能及时释放。同时咱们的需求仅仅是为了起到触发的做用,并不须要每次运行,那么能够考虑使用下面的方法,避免重复占用进程。函数
$processId = realpath(__FILE__) . '-' . get_class($this); $filename = md5($processId); $file = '/tmp/'.$filename; if(!file_exists($filename)){ file_put_contents($file, getmypid()); }else{ return true; } ## do somthing 须要长时间处理的代码 //处理完成后删除进程id记录文件 unlink($file);