php - 如何在不阻塞线程的情况下调用 PHP?

标签 php

我有 2 个 PHP 文件。一个文件是caller.php,另一个是worker.php

caller.php 将在 (linux) 系统上启动 worker.php 并且 caller.php 应该立即结束(而 worker.php 仍在服务器上工作)

worker.php 需要很多时间,它会将状态写入数据库或文件。

我希望能够在启动“php worker.php”的浏览器中打开 caller.php,关闭浏览器,在 5 分钟后返回并检查状态..(或者脚本将在完成后发送邮件) - 任何想法如何做到这一点?

最佳答案

您可以结束客户端连接并继续处理,全部完成。如果处理花费的时间超过 php/httpd 全局配置所允许的时间,您可能还想增加 php 超时。参见 set_time_limit(); .

这不完全是你问的,但我认为这可能是 X/Y 问题,所以这里我们使用的技术可用于:

  • 向用户显示处理开始页面。
  • 关闭用户连接。
  • 开始更长的处理时间。

所以基本上这回答了您描述的需求,而不是“如何做 X?”。

来电者

// Ignore user abort and set Connection close header
ignore_user_abort(true);
header("Connection: close");

// Start controlled buffering
ob_start();
echo "<h1>Processing started, come back tomorrow to see results</h1>";

// Get buffer length and manually add it to headers.
$size = ob_get_length();
header("Content-Length: $size");

// Flush buffers, user sees "Processing started" message.
ob_end_flush();
flush();

// At this point connection to client should be closed already.
// Here we start our worker, there is no need to do fork() or 
// anything like that. Client browser is not listening anymore.
// All we need to do is simply start working and start writing
// status logs to somewhere so that client can retrieve status
// with another request, let's say from checkworkerstatus.php
include "worker.php";
$worker = new worker();
$worker->start_long_processing();

不会 fork 或杀死 caller 来让 worker 单独运行?

没错,那是因为没有必要。

是的,您要求的行为是 “caller.php 将在 (linux) 系统上启动 worker.php,并且 caller.php 应该立即结束(而 worker.php 仍在服务器上工作)”。但是,如果您不想这样做,则无需这样做 multithreading-singleuser app with php .让用户 1. 开始一些事情,2. 让它运行,3. 断开用户,4. 去回到开始,用户可以在这里开始更多的事情,或者如果已经厌倦了就退出。

当然,您可以将 flush(); 之后的所有内容替换为任何内容,不同之处在于客户端不再监听,因此所有输出都会进入名为/dev/null 的黑洞。例如用这样的东西测试它:

...end_flush();
flush();

// At this point connection to client should be closed already.
echo "Nobody sees this message";
while(rand(0,10) != 1) {
    echo "Nobody sees this message";
    error_log(date("mdyHis")." Still running...");
    sleep(10);
}
...

参见 http://php.net/features.connection-handling获取更多信息。
另请阅读 http://php.net/function.flush如果刷新缓冲区和关闭用户连接似乎有任何问题。
还有一个关于Why does PHP not support multithreading?的问题(有答案)

关于php - 如何在不阻塞线程的情况下调用 PHP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11299316/

相关文章:

php - 在 xampp 等本地服务器上设置和测试 facebook 连接

php - 根据第 3 个表的计数从 2 个表中选择

javascript - Canvas 的 ToDataURL (JavaScript) 在通过 PHP 上传到服务器后创建损坏的 PNG 文件

php - 将数据数组传回服务器的最佳方式(在发布时)?

php - HTTP Referer 并不总是被传递

php - 在 foreach 循环中选择具有特定索引的行

php - 将参数从 PHP 传递到远程 shell 脚本

php - 如何限制命令行应用程序可以在 Linux Web 服务器上使用的资源

php mysql - 如何从第一页的链接中获取 ID 和日期?

javascript - 如何优化 Jquery 中的 ajax 请求?