在 PHP 中关闭连接但继续执行脚本
任何人都知道如何关闭连接(除了flush()
?),但之后继续执行一些代码。
我不希望客户端看到页面完成后可能发生的漫长过程。
Anyone know how to close the connection (besides just flush()
?), but keep executing some code afterwards.
I don't want the client to see the long process that may occur after the page is done.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你可能想看看
pcntl_fork()
——它允许你分叉你的当前脚本并在单独的线程中运行它。我在一个项目中使用了它,其中用户上传文件,然后脚本对其执行各种操作,包括与第三方服务器通信,这可能需要很长时间。初始上传后,脚本分叉并向用户显示下一页,然后父进程自行关闭。然后子进程继续执行,并由返回的页面使用 AJAX 查询其状态。它使应用程序的响应速度更快,并且用户在执行时可以获得有关状态的反馈。
此链接详细介绍了如何使用它:
如果您无法使用
pcntl_fork
,您可以随时回退到快速返回一个页面,该页面会触发 AJAX 请求来执行更多项目从队列中。You might want to look at
pcntl_fork()
-- it allows you to fork your current script and run it in a separate thread.I used it in a project where a user uploaded a file and then the script performed various operations on it, including communicating with a third-party server, which could take a long time. After the initial upload, the script forked and displayed the next page to the user, and the parent killed itself off. The child then continued executing, and was queried by the returned page for its status using AJAX. it made the application much more responsive, and the user got feedback as to the status while it was executing.
This link has more on how to use it:
If you can't use
pcntl_fork
, you can always fall back to returning a page quickly that fires an AJAX request to execute more items from a queue.遗憾的是,直到漫长的过程完成之后,页面才完成 - 因此您所要求的恐怕是不可能的(以您推断的方式实现) 。
Jhong 的回答指出了这里的关键,而 animusen 的评论则相反,我们作为 Web 开发人员使用 HTTP 的全部目的是尽快响应请求/结束 - 就是这样,所以如果你'如果你正在做其他事情,那么它指出了一些可能会更好一点的设计决策:)
通常,您在返回“页面”后执行您正在执行的附加任务并将其移交给其他进程,通常这意味着将任务放入作业队列中,并让 cli 守护程序或 cron 作业将其拾取并执行所需的操作。
确切的解决方案特定于您正在做的事情,以及不同(一组)问题的答案;但对于这一点,它归结为:不,您无法关闭连接,并且有人会建议您考虑从该脚本/页面重构长期运行的进程。
sadly, the page isn't done until after the long process has finished - hence what you ask for is impossible (to implement in the way you infer) I'm afraid.
The key here, pointed to by Jhong's answer and inversely suggested by animusen's comment, is that the whole point of what we do with HTTP as web developers is to respond to a request as quickly as possible /end - that's it, so if you're doing anything else, then it points to some design decision that could perhaps have been a little better :)
Typically, you take the additional task you are doing after returning the 'page' and hand it over to some other process, normally that means placing the task in a job queue and having a cli daemon or a cron job pick it up and do what's needed.
The exact solution is specific to what you're doing, and the answer to a different (set of) questions; but for this one it comes down to: no you can't close the connection, and one would advise you look at refactoring the long running process out of that script / page.
查看PHP 的
ignore_user_abort
-设置。您可以使用ignore_user_abort()
函数来设置它。在以下重复问题中已经给出了(可选)使用示例(并且OP已报告其有效):
它基本上参考了 PHP 手册中的用户注释。核心是
这也是以下两个的基础,我建议您研究一下:
Take a look at PHP's
ignore_user_abort
-setting. You can set it using theignore_user_abort()
function.An example of (optional) use has been given (and has been reported working by the OP) in the following duplicate question:
It basically gives reference to user-notes in the PHP manual. A central one is
which is also the base for the following two I'd like to suggest you to look into:
不要
fork
整个 apache web 服务器,而是启动一个单独的进程。让这个进程分叉出一个继续存在的孩子。查找 proc_open 以获得 php 脚本和进程之间的完整 fd 交互。Don't
fork
the entire apache webserver, but start a separate process instead. Let that process fork off a child which lives on. Look forproc_open
to get full fd interaction between your php script and the process.我们通过将需要完成的工作插入作业队列来解决这个问题,然后让 cron 脚本定期获取后端作业。可能不完全是您所需要的,但它非常适合数据密集型流程。
(如果您有一大笔现金并且想要一个经过尝试和测试的解决方案,您也可以使用 Zend Server 的作业队列)
We solved this issue by inserting the work that needs to be done into a job queue, and then have a cron-script pick up the backend jobs regularly. Probably not exactly what you need, but it works very well for data-intensive processes.
(you could also use Zend Server's job queue, if you've got a wad of cash and want a tried-and-tested solution)