在发送HTTP响应后继续执行PHP代码。

21 浏览
0 Comments

在发送HTTP响应后继续执行PHP代码。

如何让以Apache mod_php形式运行的PHP 5.2将完整的HTTP响应发送给客户端,然后再执行1分钟的操作?

长话短说:

我有一个PHP脚本,需要执行一些长时间的数据库请求和发送电子邮件,运行时间为45到60秒。这个脚本是由我无法控制的应用程序调用的。我需要应用程序报告从PHP脚本接收到的任何错误消息(主要是无效参数错误)。

应用程序的超时延迟短于45秒(我不知道确切的值),因此将每次执行PHP脚本都记录为错误。因此,我需要PHP尽快将完整的HTTP响应发送给客户端(理想情况下,一旦输入参数验证完成),然后运行数据库和电子邮件处理。

我正在运行mod_php,因此pcntl_fork不可用。我可以通过将要处理的数据保存到数据库并从cron运行实际进程来解决这个问题,但我正在寻找一个更简洁的解决方案。

0
0 Comments

在处理初始请求的脚本中创建一个处理队列的条目,然后立即返回。然后,创建一个单独的进程(可能通过cron)定期运行队列中待处理的工作。

这是我最初想到的解决方案。另一方面,为了解决第三方应用程序的超时问题而设置一个处理队列,让我感到有些不安。

这种解决方案缺乏并行性...或者需要启动一个工作进程池来处理队列。我最终选择了将http请求发布并断开与自己本地主机的连接(根据SomeGuy在这里描述的方式),以利用现有的httpd工作进程池作为后台处理程序。

在处理初始请求的脚本中创建一个处理队列的条目,然后立即返回。然后,创建一个单独的进程(可能通过cron)定期运行队列中待处理的工作。

这是我最初想到的解决方案。另一方面,为了解决第三方应用程序的超时问题而设置一个处理队列,让我感到有些不安。

这种解决方案缺乏并行性...或者需要启动一个工作进程池来处理队列。我最终选择了将http请求发布并断开与自己本地主机的连接(根据SomeGuy在这里描述的方式),以利用现有的httpd工作进程池作为后台处理程序。

0
0 Comments

在这个设置中,您需要这样的设置

alt text

嗯,但是,根据这个图表,状态消息只有在cron执行时才会发送回客户端 - 最多5-10分钟。无论如何,很好的图表!

状态消息可以随时请求 🙂 关键是这里有两个独立的进程。但是除此之外,谢谢!

+1 哇,好图表!但是,我认为使用websockets而不是用户连续请求状态更好。

0
0 Comments

在这段代码中,我们可以看到作者想要在发送HTTP响应后继续执行PHP代码。作者的意图是在接收到银行支付成功的请求后,调用各种服务并处理大量数据,这可能需要超过10秒的时间,但银行的链接具有固定的超时期限。因此,作者在接收到请求后立即向银行发送响应,并在银行离开后继续处理数据。

代码中的

<?php
 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 !
 session_write_close(); // Added a line suggested in the comment
 // Do processing here 
 sleep(30);
 echo('Text user will never see');
?>

然而,有几个问题导致代码无法正常工作。首先,ob_end_flush()函数的行为与预期不符,需要将其与flush()函数一起调用才能正常工作。其次,如果使用会话(session),则需要在flush()之后添加session_write_close(),否则在后台处理完成之前无法在同一浏览器选项卡中使用网站。最后,如果代码在像Varnish这样的代理服务器后运行,该解决方案将无效。

根据评论中的建议,我们可以对代码进行以下修改来解决上述问题:

<?php
 ob_end_clean();
 header("Connection: close");
 ignore_user_abort(true); // 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 !
 session_write_close(); // Added a line suggested in the comment
 // Do processing here 
 sleep(30);
 echo('Text user will never see');
?>

以上修改可以解决在一些情况下代码无法正常工作的问题。

0