- 本文地址: https://www.laruence.com/2011/04/13/1991.html
- 转载请注明出处
当PHP运行在FastCGI模式时,PHP FPM提供了一个名为fastcgi_finish_request的方法.按照文档上的说法,此方法可以提高请求的处理速度,如果有些处理可以在页面生成完后再进行,就可以使用这个方法.
听起来可能有些茫然,我们通过几个例子来说明一下:
<?php echo '例子:'; fastcgi_finish_request(); /* 响应完成, 关闭连接 */ /* 记录日志 */ file_put_contents('log.txt', '生存还是毁灭,这是个问题.'); ?>
通过浏览器访问此脚本, 结果发现并没有输出相应的字符串,但却生成了相应的文件.由此说明在调用fastcgi_finish_request后,客户端响应就已经结束,但与此同时服务端脚本却继续运行!
合理利用这个特性可以大大提升用户体验,趁热打铁再来一个例子:
<?php echo '例子:'; file_put_contents('log.txt', date('Y-m-d H:i:s') . " 上传视频\n", FILE_APPEND); fastcgi_finish_request(); sleep(1); file_put_contents('log.txt', date('Y-m-d H:i:s') . " 转换格式\n", FILE_APPEND); sleep(1); file_put_contents('log.txt', date('Y-m-d H:i:s') . " 提取图片\n", FILE_APPEND); ?>
代码里用sleep模拟一些耗时的操作,浏览时没有被堵塞,程序却都执行了,具体看日志.
末了给您提个醒,Yahoo在Best Practices for Speeding Up Your Web Site中提到了Flush the Buffer Early,也就是利用PHP中的flush方法把内容尽快发到客户端去,它和本文介绍的fastcgi_finish_request有些许的类似.
转载附言: 我看了下这个方法, 在调用的时候, 会发送响应, 关闭连接. 但是不会结束PHP的运行. 相比调用flush, 或者我之前介绍的加速你的Echo来说, 这个方法能更加干脆一些.
另外, 从代码的可移植性讲的话, 可以在代码中附上如下代码:
if (!function_exists("fastcgi_finish_request")) { function fastcgi_finish_request() { } }
不会造成代码部署在非fpm环境下造成问题.
[…] 返回值: 成功时返回TRUE,失败时返回FALSE 鸟哥的例子:(https://www.laruence.com/2011/04/13/1991.html)、 <?php echo ‘你看的见我。‘; fastcgi_finish_request(); /* 响应完成, […]
使用fastcgi_finish_request提高页面响应速度 | 风雪之隅 http://generasiqq.club
[…] 内容参考鸟哥博客使用fastcgi_finish_request提高页面响应速度 […]
[…] 本文地址: http://www.laruence.com/2011/04/13/1991.html […]
max_execution_time会影响它的执行吗?
这个和 comet 用途有什么区别?
It’s going to be ending of mine day, but before ending I am
reading this fantastic paragraph to increase my experience.
Look at my web-site … 1031 exchange
我用独立的php 文件
简单写了个
sleep 150
<?php
echo fastcgi_finish_request();
set_time_limit(0);
sleep(150);
exit;
却没有阻塞的情况,应该是唯一入口中某种情况造成的,但是是什么呢???
哦。刚才又测试了下 直接用 sleep 进行延时
问题依旧,不过这次换浏览器不阻塞了
偶尔同一个浏览器会有响应
阻塞超时返回的是 504 Gateway Time-out
实际应用中发现一个问题
fastcgi_finish_request 后
如果脚本执行时间长,在执行结束之前,触发此事件的机器,无论切换浏览器,再也打不开执行相同php(唯一入口)的页面了,直到脚本执行完成才行,被阻塞了
具体环境
nginx+php 5.4
脚本中 fastcgi_finish_request 后,是执行curl的大量循环。
但是服务器肯定是运行好好的,如果不是访问那个唯一入口php,或者换一台机器就没有阻塞问题
浏览器返回的错误是网管错误
[…] 本文地址: http://www.laruence.com/2011/04/13/1991.html […]
[…] 使用fastcgi_finish_request提高页面响应速度 […]
@nroe 用__destruct干啥呢?
为啥不用 public function __destruct() ?
不错啊,很有帮助,不过Mod_php不能使用。
fastcgi_finish_request之后的代码,虽然不占Web服务器时间,快速响应。后边的代码还是要占用fastcgi进程的时间。可以用异步事件模式。将请求插入到高速消息队列中,然后在守护进程中完成。
http://www.swoole.com/news/55.html
活捉一只大佬
[…] http://www.laruence.com/2011/04/13/1991.html 使用fastcgi_finish_request提高页面响应速度 […]
很不错的学习资料,能在自己网站上尝试。或许能少走不少歪路。
@CFC4N 你的这个例子应该使用异步处理来完成:)
这步应该做异步队列的插入,而不是连接smtp。。。
那如何知道程序执行完?
这样一下,像登录的话,可能涉及很多复杂的东西可以我们可以放在”伪后台执行(fastcgi_finish_request)”,
但是如果数量多的话, 就会出现超时的现象, 可以在头部加入set_time_limit(0);
[…] 2011/04/13, ryan writes: 嗯,尽量早的flush,我也觉得很好,facebook的pagelet模式我已经开始用了,感觉不错~~~ […]
很不错啊,受教
嗯,尽量早的flush,我也觉得很好,facebook的pagelet模式我已经开始用了,感觉不错~~~
这确实是太好了,这个优点可以用于那些长时间执行的代码转为”后台执行”。类似制造了一个“任务中间层”去执行这些耗时的操作,比如用户找回密码的时候,可以直接返回找回成功,后台连接SMTP发送邮件,连接SMTP所耗时完全不需要用户等待返回,可先告诉用户已经完成,提高用户体验。