【问题标题】:PHP asynchronous tasks - sending results to browser when readyPHP异步任务 - 准备好后将结果发送到浏览器
【发布时间】:2013-05-03 00:50:40
【问题描述】:

在 PHP 中,我想并行运行几个独立的任务。每个任务都会产生一个结果,我想在结果准备好后将其发送回访问者的浏览器。这个想法是使用正常加载页面,然后使用 HTML5 SSE(服务器发送的事件)在数据可用时将数据发送到浏览器,同时使用keep-alive 保持 HTTP 连接打开。我不只是想刷新输出;我将执行很多不同的任务,这些任务都非常适合并行运行,所以我不想同步执行它们。

我最初的想法是使用pthreads extension 进行多线程处理。我不确定线程​​是如何与 PHP 一起工作的。只要我有一个线程正在运行,与浏览器的连接是否会保持打开状态,即我可以安全地将数据从线程发送回浏览器吗?我认为 pthreads 相当稳定,但我不相信我应该使用它,因为它是实验性的。

pthreads 曾经是,现在也是,结果非常好。任何 其限制或功能可能随时更改;这就是性质 实验。

然后我想起了 Gearman,它允许我使用工人来完成我的任务。我需要后台工作人员,因为我不希望我的脚本执行在等待作业完成时阻塞,因为我想并行运行多个作业。这对 Gearman 来说没有问题,但如果我使用后台工作人员,我很不确定能否将结果发送回 Gearman 客户端。据我了解,后台工作人员将在自己的进程或上下文中运行,所以我想这意味着我无法从后台工作人员将数据发送回浏览器?我注意到GearmanClient class 提供了一些设置回调的方法,但据我从研究中了解到的,似乎这些回调仅通过同步调用调用。理想情况下,我要么想直接从我的后台工作人员那里发回结果(我怀疑这是可能的),要么让后台工作人员在完成时通知客户端,而不必调查 Gearman 的工作状态。回调处理程序将是最佳选择,因为我可以从那里发回数据。

我还考虑将 ActiveMQ 等消息传递系统(或 memcached)与ZendQueue 一起使用。这个想法是在一个通道上发送工作请求,然后在不同的通道上监听结果。当从结果通道读取消息时,消息会直接发送到浏览器。缺点是我会做额外的工作,例如将结果消息映射到请求。

最后,我非常倾向于使用 Gearman 方法,但我不确定是否有可能实现我想要的。总而言之,我想执行每个最多需要几秒钟的并行任务,并在结果准备好时将它们单独发送回浏览器(通过使用 HTML5 SSE)。

我的方法可行吗?你还有其他建议吗?提前非常感谢!

【问题讨论】:

  • 我当然不知道你的答案,但我很好奇谁做了,它是什么!
  • 如果可能的话,我认为一个好的解决方案是使用 Ajax。如果是,我会为你写一个答案。我从未与 Gearman 合作过,但也许下面的链接可以给你一些想法:phpclasses.org/blog/post/…
  • 你读过 RabbitMQ 吗?它是一个 AMQP 实现。它可能对您的情况有用。阅读官方这里的第六个例子rabbitmq.com/tutorials/tutorial-six-java.html(例子是java,但是那里有足够的php例子)。
  • @Nick 除非我误解了你的意思,否则 AJAX 似乎不适合这个。我希望能够并行执行相当多的任务,这将需要与 Web 服务器的 HTTP 连接一样多。您发布的链接对于一般使用 Gearman 非常有用,但不幸的是,当工作人员完成工作时,Gearman 客户端似乎没有收到通知。感谢您的想法!
  • @Guumaster 这不是一个坏主意,尽管我认为 RabbitMQ 并没有为我提供 ActiveMQ 没有的很多东西(在你引用的示例中)。但是有几个选择是好的! :-) 考虑更多之后,我看不出使用消息队列不起作用的任何原因。不过,我有一些挑战,但总的来说,这个想法听起来是可信的。感谢提到 RabbitMQ;我以前没有听说过那个项目。

标签: php html asynchronous pthreads gearman


【解决方案1】:

我只能回答 pthreads 部分。

目前还不支持持久线程,因此在每个请求结束时,所有创建的上下文都会被销毁(加入)。直接从线程发送数据到浏览器可能是个坏主意(在某些设置中会导致崩溃),原因是 Zend 级别无法控制 apache 或您正在使用的任何 sapi 的输出,所以 pthreads 不努力连接标准输出或任何其他的……想法应该是让接受连接的线程(或进程)使用它创建的线程中的数据来处理到客户端的输出……

持久化线程有点问题,PHP 并不真正支持持久化对象,mysqli 等提供持久化对象的方式与 pthreads 对持久化线程的要求不同,首先,它们的接口始终相同(即,它实现mysqli),其中 pthreads 由用户在 PHP 中实现。即使我要解决这个问题,我也可以想象它们很容易被误解,我对持久线程的实验仍在继续,如果或当我找到合适的实现时,文档将会更新。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多