【问题标题】:Close connection in PHP but keep executing script在 PHP 中关闭连接但继续执行脚本
【发布时间】:2010-07-17 05:44:04
【问题描述】:

任何人都知道如何关闭连接(除了flush()?),但之后继续执行一些代码。

我不希望客户端看到页面完成后可能发生的漫长过程。

【问题讨论】:

  • 为什么你也需要? PHP 只需要几毫秒就可以运行一个普通的脚本。任何需要更长时间的东西都不应该被公众访问。
  • animuson,虽然我总体上同意您的说法,但我们不知道该应用程序/网站是否可供公众访问。它很可能是在某处内部运行的应用程序。所以我看不到你的评论的相关性......

标签: php buffering


【解决方案1】:

您可能想查看pcntl_fork()——它允许您派生当前脚本并在单独的线程中运行它。

我在一个项目中使用它,用户上传文件,然后脚本对其执行各种操作,包括与第三方服务器通信,这可能需要很长时间。初始上传后,脚本分叉并向用户显示下一页,父进程自行关闭。然后子进程继续执行,并由返回的页面使用 AJAX 查询其状态。它使应用程序的响应速度更快,并且用户可以在执行时获得有关状态的反馈。

这个链接有更多关于如何使用它:

如果您不能使用pcntl_fork,您始终可以退回到快速返回一个触发 AJAX 请求以执行队列中的更多项目的页面。


mvds 提醒以下内容(可以应用于特定的服务器配置): 不要fork 整个 apache 网络服务器,而是启动一个单独的进程。让这个过程产生一个继续存在的孩子。查找proc_open 以获得您的 php 脚本和进程之间的完整 fd 交互。

【讨论】:

  • 请注意,您只能将 pcntl_fork()(在此上下文中)与用 php 本身编写的定制 http 服务器一起使用 - 因此通常只能在大约 0.0001% 的时间内使用此响应;)
  • 那么我认为你 fork 整个 apache 守护进程。这不是一个漂亮的景象,可能不是 apache 模块的预期用途......
  • 我相信它分叉了 apache 工作进程,该进程将是众多进程之一(尽管默认情况下太多了)。再加上普通的 linux 服务器非常擅长分叉进程这一事实,让我预计它不会像您预期的那样有问题。不过,我的经验不是针对任务关键型应用程序。正如我所说,这只是解决方案的一小部分——解决方案的主要架构是正确设置客户端 - 服务器模型。
【解决方案2】:

我不希望客户看到 之后可能发生的漫长过程 页面完成。

遗憾的是,页面直到 漫长的过程完成后才完成 - 因此您要求的内容是不可能的(以您推断的方式实现)我害怕。

这里的关键,正如 Jhong 的回答所指出的,并且被 animusen 的评论相反地建议,是我们作为 Web 开发人员使用 HTTP 所做的全部重点是尽快响应请求 /end - 就是这样,所以如果您正在做其他事情,那么它指出了一些可能会更好的设计决策:)

通常,您在返回“页面”后执行您正在执行的附加任务并将其交给其他进程,通常这意味着将任务放入作业队列并让 cli 守护程序或 cron 作业将其拾取做需要做的事。

确切的解决方案是特定于您正在做的事情,以及不同(一组)问题的答案;但是对于这一点,它归结为:不,您不能关闭连接,并且建议您考虑从该脚本/页面中重构长时间运行的进程。

【讨论】:

    【解决方案3】:

    看看PHP's ignore_user_abort-setting。您可以使用ignore_user_abort() function 进行设置。

    在以下重复问题中给出了example of (optional) use(并且据报告由 OP 工作):

    它基本上参考了 PHP 手册中的用户注释。一个中心是

    这也是我建议您研究以下两个的基础:

    【讨论】:

    • 这是实际的最佳答案。他说客户端不需要知道过程的结果,所以他不需要使用分叉、队列或任何类似的东西。
    • @pjbeardsley:实际上这不是最好的答案,因为它带有一些未被注意到的问题:首先,根据链接来源,ingnore_user_abort 是可选的,但命名为首先也是必要的。其次,此处提供的答案已在较早前给出,并且没有关联。源代码也丢失了(这也是链接副本的问题,但现在已修复)。但是,提供的链接示例可以很好地完成您对某些 webserver / php 配置所说的内容,并且是某种common。所以这也不是一个完全错误的答案。
    【解决方案4】:

    不要fork 整个 apache 网络服务器,而是启动一个单独的进程。让这个过程产生一个继续存在的孩子。查找proc_open 以在您的 php 脚本和进程之间获得完整的 fd 交互。

    【讨论】:

    • 这可能是对现有答案的补充,尤其是您越担心 pcntl_fork 会在 Apache SAPI 模块使用中非常特殊的 Apache + PHP 中做一些坏事/资源密集型。这应该是对现有答案的评论或对使用该答案时要考虑的事情的额外编辑,而不是额外的答案,因为它的价值并不清楚。我合并了它,我要求你删除它。 - 另外,当我考虑更多时,应该有一些参考资料可以更好地解释这一点,比如链接,也许是 PHP 中的fork。
    • @hakre 我不同意你的看法。问题是“在运行 PHP 脚本后如何运行代码”,答案是“改为启动一个单独的进程。让该进程派生出一个继续存在的子进程。寻找 proc_open 以在您的 php 脚本之间获得完整的 fd 交互和过程。”
    • @hakre,如果您不同意,只需投反对票,这就是本网站的运作方式。
    【解决方案5】:

    我们通过将需要完成的工作插入作业队列来解决此问题,然后让 cron-script 定期提取后端作业。可能不完全是您所需要的,但它非常适用于数据密集型流程。

    (如果您有大量现金并想要一个久经考验的解决方案,您也可以使用 Zend Server 的作业队列)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      相关资源
      最近更新 更多