【问题标题】:Execute a long time background process in symfony在symfony中执行长时间的后台进程
【发布时间】:2018-02-16 18:21:49
【问题描述】:

我一直在阅读如何解决我的问题,但我找不到解决方案。

我正在使用 symfony,当用户调用操作时,我有很长的时间要执行。请求完成后我可以处理数据吗?目的是使用 jQuery 从客户端启动轮询进程并等待进程完成以重定向到另一个操作。

现在,我正在使用 ContainerAwareCommand 执行此操作,但它会等到后台进程完成。

拜托,你能帮帮我吗?

提前致谢。

【问题讨论】:

  • 好吧。用户向服务器发出 POST 请求,包括一个大文件。我需要处理该文件,但我不想在处理完成之前阻止请求。我的目的是在后台处理那个大文件,并从浏览器轮询以了解进程何时完成。你有足够的细节吗?

标签: php symfony


【解决方案1】:

是的,在向用户发送响应后,可以在 Symfony 中执行一些后台进程。

你需要为kernel.terminate事件写一个监听器。 并在回调中定义您的长期运行过程。

请注意以下几点:

  • 如果以编码的 gzip 格式发送响应,则此技术不起作用。所以,你应该强制 apache/nginx 不要使用 gzip 来处理这个特定的响应。
  • 在此请求期间设置任何会话数据非常复杂,因为只有在您的长时间运行的进程完成后才会设置会话。这意味着,您需要找到闪存袋消息的替代方法。

【讨论】:

  • 嗨@Maksym Moskvychev!正如您建议我的那样,我已经为 kernel.terminate 事件实现了一个侦听器,但是即使我在文档中阅读时修改了我的 AppKernel 以实现 TerminableInterface,来自浏览器的请求也不会结束,直到我在此侦听器中执行的方法结束。公共函数 onTerminate(PostResponseEvent $event) { sleep(60); } 公共静态函数 getSubscribedEvents() { 返回数组( KernelEvents::TERMINATE => 'onTerminate', ); } 你知道问题出在哪里吗?提前致谢。
  • 你在使用 app_dev.php 吗?通常这只适用于产品环境。还要检查浏览器中的网络选项卡,是否有 content-encoding: gzip 标头?如果是 - 那么这是一个问题。
  • 是的,似乎启用了gzip。我正在搜索如何仅为此操作禁用它,但我找不到解决方案。我对 .htaccess 不是很熟悉,我不知道是否可以直接从 Symfony 中的代码禁用压缩。
  • 你可以从 Symfony 中禁用它。你用的是什么服务器?
  • 在开发环境中,我使用的是 Apache。
【解决方案2】:

这对于诸如 RabbitMQ 或 Redis 之类的 队列 来说是一个很好的例子。在上传每个文件时将消息放入队列。从队列中读取一个或多个PHP daemons,处理每个文件,并为用户更新状态(例如更新数据库中的一行)。

这使您可以在独立于 Web 请求的服务器上运行处理并轻松扩展。如果您需要做的事情允许的话,您还可以使用队列将您的处理分解为多个并发任务。

【讨论】:

  • 感谢您的回复。你认为这是我的问题的最佳解决方案吗?如果我理解你的话,守护进程将永远运行,可能每 15 秒读取一次数据库,这可能太多了。请记住,用户正在等待和轮询,直到进程结束。非常感谢您的帮助。
  • 我认为这是最具扩展性的解决方案。守护进程从队列中处理并更新数据库中的状态。您的应用程序的前端可以每 15 秒发出一次 AJAX 请求以检查数据库中的状态。这负担不大。或者用户可以离开页面,当他们回来时仍然可以找到状态。
猜你喜欢
  • 1970-01-01
  • 2013-11-23
  • 2018-02-05
  • 2016-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 2012-01-14
相关资源
最近更新 更多