PHP提前关闭连接。如果完成任何输出,脚本将挂起

PHP提前关闭连接。如果完成任何输出,脚本将挂起,php,Php,我正在使用以下命令提前关闭与客户端的连接: 工作正常,但在此事件之后,如果某个脚本输出任何内容(通过回显或添加新标题),脚本将从此点停止执行。 我尝试在提前关闭后启动输出缓冲,然后丢弃它,但它不起作用: Server::early_close(); ob_start(); heavy_work(); ob_clean(); 有什么想法吗? 使用PHP5.3.x我想你不应该走这条路。Http请求应该尽可能短以提高可用性 如果需要执行一些“繁重的处理”,您可以使用某种队列“安排”它。服务器上的单

我正在使用以下命令提前关闭与客户端的连接:

工作正常,但在此事件之后,如果某个脚本输出任何内容(通过回显或添加新标题),脚本将从此点停止执行。
我尝试在提前关闭后启动输出缓冲,然后丢弃它,但它不起作用:

Server::early_close();
ob_start();
heavy_work();
ob_clean();
有什么想法吗?

使用PHP5.3.x

我想你不应该走这条路。Http请求应该尽可能短以提高可用性

如果需要执行一些“繁重的处理”,您可以使用某种队列“安排”它。服务器上的单独进程/守护进程可以从队列中拾取这些作业以执行它们。然后,http应用程序可以检查此类作业是否仍在等待处理/是否已启动/是否已完成

有许多库可用于实现此目的:、等

Http请求并不真正适合长时间操作,这就是为什么在尝试这样做时会遇到各种各样的问题:)

更新


如果您无法在服务器上使用库(如Gearman等),您可以构建自己的基于文件或数据库的队列,从应用程序内部将“命令”推送到队列中,并让cronjob读取该队列并执行这些任务。

您需要echo chr(0);在echo$output;之后;。发送空字节将强制浏览器结束连接。另外,我假设在服务器::early_close()之前有一个ob_start()?如果没有,您将需要这样做才能使ob_get_length正常工作。

实现这一点的经典代码是:

ob_end_clean();
header("Connection: close");
ignore_user_abort();              // optional ob_start();

echo ('Text the user will see');

$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();                   // Strange behaviour, will not work
flush();                          // Unless both are called !

// Do processing here
sleep(30);

echo('Text user will never see');

否则,如果要执行异步调用,我建议您阅读以下内容:

根据您迄今为止的评论,我建议在页面加载时使用AJAX请求替换当前解决方案。不要过早地关闭连接并继续在服务器上处理,而是像通常那样提供响应,并添加一个AJAX请求,以便在页面加载到客户端后添加任何附加处理。这将完全消除无关输出的问题,并且您还可以将任何成功/失败消息发送回用户


另一种解决方案是将您的工作在表或内存中排队,并设置一个cron在后台处理。

是一个简单的
die()
verboten?I
die()
在这里没有帮助,因为请求是在服务器收到执行
繁重工作的命令后立即回答客户机。客户无需等待繁重的工作结束。放置
die()
而不是
Server::early\u close()
可以避免执行
繁重的工作()
。如果HTTP回复结束,请不要尝试保持Web服务器线程运行。使其成为异步作业。Gearman和类似的工具可以为您处理很多细节,但任何工作(-queue)都可以。我会尝试这种替代方法,但我恐怕无法在服务器上使用。我忍不住要问。为什么您要在
繁重的工作()
中输出任何内容或修改标题?对请求的响应已在
flush()
上发送,因此您没有端点可响应?这就是为什么我会尽快关闭连接的原因您依赖的是进程一直在运行以执行所需的操作,但您无法保证这会成功,也不向用户报告失败。+1使用后台任务解决方案(甚至是自己的实现)比依赖孤立的http请求来完成而不会出现错误是更好的主意和更健壮的。我同意这不是一个干净的解决方案(我计划使用库/开发自己的来更好地处理此问题)我只是好奇,一个简单的回声怎么会挂上我的行刑?你怎么考虑不走这条路?你需要做你需要做的事。有时,仅仅假设脚本将及时运行是不可能的。我正确地关闭了连接,似乎失败的是,如果在我繁重的工作中有任何输出,脚本将停止执行,我想知道为什么以及我是否可以避免它。你确定这是关于一些输出吗?是否存在超时/内存限制等?是的,当我在“繁重的工作”中放置回显时,它不会结束其执行,只是在执行回显的同一行停止。当这个回音被注释时,脚本成功结束。如果您测试上面的内容,它是否工作?如果是,从代码开始重写代码,并逐段添加(每次测试),直到代码“中断”。)您的代码对我来说似乎不起作用,我不得不在开头添加
ob\u start
。一旦我这样做了,是的,我进行了测试,代码就结束了,所以我想我的代码中还有其他东西导致了这个问题。因为你让我意识到php正确地处理了这个问题,所以我给你赏金。非常感谢。此脚本已通过ajax调用请求。我发现,如果没有提前关闭,请求时间就没有了。哦,在这种情况下,你可以延长超时时间,而不是提前关闭连接。虽然如果您有长时间运行的后台进程,我强烈建议使用cron(同样是长超时)。是的,有一个
ob\u start()
调用。
ob_end_clean();
header("Connection: close");
ignore_user_abort();              // optional ob_start();

echo ('Text the user will see');

$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();                   // Strange behaviour, will not work
flush();                          // Unless both are called !

// Do processing here
sleep(30);

echo('Text user will never see');