php 在 echo 之后是不是就不能执行后续代码了?

2015-03-23 10:56:29 +08:00
 kisshere
一个常用的ajax请求json过程:
<?php
...
echo json_encode($callbackData);
exit;
?>
现在由于请求这个ajax之后,服务器还要执行一个耗费很长时间的函数longtime(),我就在想能不能在echo json_encode($callbackData);之后执行longtime()这样可以避免用户等待很久的时间,又能继续让服务器执行longtime()函数?
<?php
...
echo json_encode($callbackData);
longtime():
exit;
?>
目前采用的是ajax二次请求的形式,即:
$.post(targetUrl,{obj:obj},function(){
$.post(execute_longtime_url)
})
服务器端设置set_time_limit(0)和ignore_user_abort,但这样我每次都要请求两次服务器,求高手解答,手机码字不易,谢啦
6217 次点击
所在节点    程序员
6 条回复
yaxin
2015-03-23 11:00:02 +08:00
消息队列,能解决你的问题
kisshere
2015-03-23 11:01:28 +08:00
@yaxin 大神能详细点吗?
raincious
2015-03-23 11:08:11 +08:00
@kisshere

就是将昂贵的操作交给消息队列。

比如你可以不在这个PHP程序里处理那个longtime操作,直接输出好给用户,然后请求消息队列来进行处理。

不过PHP是可以在输出之后仍然继续运行的的,不过具体操作有点Hack。你需要忽略用户的关闭请求,用ignore_user_abort,然后在数据输出之后立即用flush和ob_flush之类来关闭输出缓存,让上层(Apache、Nginx之类)知道你结束响应了,之后你就可以Happy的继续玩你的了。

但是PHP不太适合执行长时间的任务,Apache的那个线程会被锁死直到释放,注意。

斗胆拿这段代码供你参考下:
https://github.com/raincious/facula/blob/master/src/Facula/Base/Prototype/Core/Response.php#L506
注意ob已经在436行打开过了。
freefcw
2015-03-23 11:20:57 +08:00
优先还是考虑使用消息队列之类的在别的地方处理,主要原因#3说的比较清楚了。对于单线程的php来说,执行这种长时间的任务会影响你的并发,而且也不方便后期的拆解模块。

如果使用php-fpm的话,可以使用fastcgi_finish_request这个函数,在输出以后继续执行你的php代码,详见

http://php.net/manual/zh/function.fastcgi-finish-request.php
simman
2015-03-23 11:21:49 +08:00
肯定要用队列了,主要是异步问题。
cute
2015-03-23 11:21:52 +08:00
php-fpm可以这样,还是建议使用服务端异步队列

fastcgi_finish_request();
longtime();

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/178739

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX