您可以结束客户端连接并继续处理,全部完成。如果处理时间超过 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();
不分叉或杀戮caller
以worker
独自奔跑?
没错,那是因为没有必要。
是的,您要求“caller.php 将在(linux)系统上启动 worker.php 并且 caller.php 应立即结束(而 worker.php 仍在服务器上工作)”的行为。但是,如果您不想使用 php 执行 multithreading-singleuser 应用程序,则无需这样做。让用户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 。
还有另一个问题(有答案)关于为什么 PHP 不支持多线程?