1

我有两个用户可以调用的脚本(A 和 B)。

如果用户调用 A,我会做一堆数据库访问并检索结果返回给用户。在我弄清楚我需要发回的内容之后,我会对数据库进行大量额外的处理和修改。

我想知道是否可以将结果返回给用户,然后在某种后台任务中执行其余的处理。

更进一步的条件是,如果调用脚本A的用户随后调用脚本B,则用户调用A触发的任何处理任务必须完成,或者脚本B必须等待直到它完成。

有没有办法做到这一点?

4

4 回答 4

1

关闭请求后,php 无法执行任务,因为请求(以及发送到浏览器的响应)在 php 进程完成时真正关闭。

此外,php 适合短期操作,而不是像守护进程这样长时间运行的程序,因为 php 缺乏良好的垃圾收集器(因此它会在崩溃之前耗尽所有可用内存)。

您要查找的内容称为队列。当您需要执行一些资源(或时间)密集型任务时,您将任务放入队列中。然后稍后一个工作进程将从队列中取出一个项目然后执行任务。

这使您能够通过限制工作人员的数量来限制资源使用,以避免出现高峰和服务故障。

查看 resque(对于自托管解决方案)或 iron.io(对于云,设置免费解决方案)

如果您在共享主机上(因此,没有可用的队列和 cron),那么我建议您查看 iron.io 推送队列。当队列不为空时,这种队列将调用您的服务器(通过 HTTP)向其发送任务。这样,所有轮询/检查队列都在 iron.io 端完成,您只需设置一个常规页面即可执行您的任务。

此外,如果您希望脚本 B 等待脚本 A 完成,则必须创建某种锁定系统。但如果我是你,我会尽量避免这种情况,因为这会导致死锁(一个线程等待另一个线程,但另一个线程永远不会完成,从而永远阻塞等待的线程)

于 2013-08-26T09:15:42.530 回答
0

你可以这样做:

一个.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);

笔记:

  • 不是最优雅的解决方案,但它可以完成工作。
  • 如果您希望一次只运行一个 b.php,您可以添加一个 pid 检查。
  • 该过程将使用 http 用户(apache 或其他)运行,确保它具有适当的权限。
于 2016-07-18T19:34:37.990 回答
-1

我猜你正在寻找Ignore_user_abort(). 当浏览器关闭连接时,此功能使您的脚本保持活动状态以进行清理任务。

http://php.net/manual/en/function.ignore-user-abort.php

header()您可以通过, set_time_limit(), ignore_user_abort(),的良好组合虚拟地分叉浏览器请求connection_status()

与 Ajax 结合起来非常有趣。

于 2013-08-26T09:24:39.583 回答
-1

做这样的事情最好使用nodejs,PHP 是同步的,并逐行完成它的工作。(你也可以在lib之类python的其他东西中开发异步代码)。asyncore

但是对于您的问题,您应该开发如下内容:

set_time_limit(0);
ignore_user_abort();
// Working With database
// Echo data to user
ob_end_flush(); 
ob_flush(); 
flush(); 
// Second part of database access,this can be take longer 

看看ob_flush() php 函数,它不会等待结束进程,然后为用户呈现 html。

于 2013-08-26T09:34:08.837 回答