我有两个用户可以调用的脚本(A& B)。
如果用户调用A,我会进行一堆数据库访问并检索结果以返回给用户。在我找到了我需要发回的内容之后,然后我做了一堆额外的处理和修改数据库。
我想知道是否可以将结果返回给用户,然后在某种后台任务中执行剩余的处理。
另一个条件是,如果调用脚本A的用户然后调用脚本B,则用户通过调用A触发的任何处理任务必须完成,否则脚本B必须等到它完成。
有办法做到这一点吗?
答案 0 :(得分:1)
Php在关闭请求后无法执行任务,因为当php进程完成时,请求(以及发送给浏览器的响应)确实已关闭。
另外,php适用于短操作,不会像守护程序一样长时间运行,因为php缺少一个好的垃圾收集器(所以它会在崩溃之前吃掉所有可用的内存)。
您正在寻找的是一个队列。当您需要执行某些资源(或时间)密集型任务时,可以将任务放入队列中。然后,工作进程将从队列中获取一个项目,然后执行该任务。
这使您可以通过限制工作人员数量来限制资源使用,以避免峰值和服务失败。
看看resque(用于自托管解决方案)或iron.io(用于云,免费安装解决方案)
如果您在共享主机上(因此,没有队列且没有可用的cron),那么我建议您查看iron.io推送队列。当队列不为空时,那种队列将调用您的服务器(通过HTTP)向其发送任务。这样,所有轮询/检查队列都在iron.io端完成,您只需设置一个执行任务的常规页面。
此外,如果您希望脚本B等待脚本A完成,则必须创建某种锁定系统。但是我会尽量避免这种情况,如果我是你,因为这会导致死锁(一个线程在等待另一个线程,但另一个线程永远不会完成从而永远阻塞等待线程)
答案 1 :(得分:0)
你可以这样做:
a.php只会
<?php
echo "hi there!";
//in order to run another program in background you have to
//redirect std e err output and use &
//otherwise php will wait for the output
$cmd = "/usr/bin/php ".__DIR__."/b.php";
`$cmd > /dev/null 2> /dev/null &`;
echo "<br>";
echo "finished!";
b.php
<?php
$f = fopen(__DIR__."/c.txt", "w");
//some long running task
for($i=0; $i<300; $i++){
fwrite($f, "$i\n");
sleep(1);
}
fclose($f);
注意:
答案 2 :(得分:-1)
我猜您正在寻找Ignore_user_abort()
。
当浏览器关闭连接时,此函数可使脚本保持活动状态以进行清理任务。
http://php.net/manual/en/function.ignore-user-abort.php
您可以通过header()
,set_time_limit()
,ignore_user_abort()
,connection_status()
的良好组合来虚拟地解决浏览器请求。
与Ajax结合使用非常有趣。
答案 3 :(得分:-1)
做这样的事情最好使用nodejs
,PHP是同步的并且逐行完成它的工作。(你也可以通过{{1}开发异步代码,如python
。 lib)。
但是对于你的问题,你应该开发类似的东西:
asyncore
看看ob_flush() php函数,这不会等到结束进程,然后为用户渲染html。