【问题标题】:Using RabbitMQ in a webapplication, can multiple threads work on the same queue在Web应用程序中使用RabbitMQ,多个线程可以在同一个队列上工作
【发布时间】:2014-10-07 12:52:42
【问题描述】:

我有一个网络应用程序,用户在其中上传由网络应用程序处理的文件。我做的第一件事是将请求放入 RabbitMQ 队列。然后这些请求在后台以排队的方式一个接一个地处理。所有这一切都很好。

根据我的分析,我注意到当队列中的一个请求需要很长时间来处理时,就会出现问题。发生这种情况时,长时间运行的请求背后的请求也会延迟。

示例

User 1 uploads DOC file   at 12:32:10*
User 2 uploads DOCX file  at 12:32:11*
User 3 uploads PDF file   at 12:32:12*
User 1 uploads PPT file   at 12:32:13*

* - 数据库中反映当时请求创建的日期时间戳

此时队列将如下所示并按以下顺序排列:

DOC, DOCX, PDF, PPT

我知道PDF 文件需要更长的时间来处理,但PPT 不需要很长时间。由于PDFPPT 之前处理,PPT 也需要很长时间才能完成。

处理完所有请求后,DB 中的时间戳如下所示:

User 1 uploads DOC file   at 12:32:10*     12:32:11**
User 2 uploads DOCX file  at 12:32:11*     12:32:12**
User 3 uploads PDF file   at 12:32:12*     12:32:20**
User 1 uploads PPT file   at 12:32:13*     12:32:40**

** - 数据库中反映请求完成的日期时间戳

请注意,PPT 需要 27 秒才能完成,因为它落后于 PDF。在我的测试中,如果它在PDF 之前,那么它只需要2 to 3

PS:我在 grails 应用程序中使用 RabbitMQ 插件

问题

有没有办法让多个线程处理 Web 应用程序中队列中的请求?我在想,如果多个线程在队列上工作,那么即使一个请求(上面示例中的 PDF)需要更长的时间来处理其他请求,仍然可以完成(上面示例中的 PPT)?如果是这样,我怎样才能强制多个线程在队列上工作?

是否有更好的架构我应该使用,以便更快地处理请求,而不是等待需要很长时间才能处理的请求?

【问题讨论】:

  • 不清楚你想要什么。您是否希望在单个 Web 请求期间多个线程开始并行使用来自同一队列的消息?如果是这样,那就去做吧。没关系,但要注意客户端库的实现,以便在多线程环境中正确使用它。如果您担心某些消费者处理长消息,没关系。停滞的消息不会阻止其他消费者使用消息。
  • @zaq178miami 是的,我希望多个线程在队列上工作,这样长时间运行的任务就不会延迟处理它后面的任务。我用一个详细的例子更新了我的问题

标签: grails queue rabbitmq messaging


【解决方案1】:

也许您想要的是将多个消费者附加到您的队列中。因此,当一个消费者处理 PDF 时,另一个消费者可以处理下一个文件。

在您的情况下,您可能还希望 basic_qos 具有较低的值。看看这个教程:http://www.rabbitmq.com/tutorials/tutorial-two-java.html

此模式在此处称为competing consumershttp://www.eaipatterns.com/CompetingConsumers.html

【讨论】:

  • 嗯,我对more than one consumer 感到困惑。处理 PDF(和 PPT)的代码是我的网络应用程序的一部分。这是否意味着我需要将这些代码片段移植出来并将它们转换为不同的应用程序/服务?
  • FWIW,我正在使用这个插件来处理 RabbitMQ grails.org/plugin/rabbitmq
  • 我不习惯 grails,但是在 RabbitMQ 中,您通常让您的消费者在后台运行,与您的 web 应用程序分开。然后你可以运行它们的许多实例
【解决方案2】:

这不会违背使用队列的目的吗?我们有一个使用 RabbitMQ 的类似应用程序。我们所做的是为每种类型设置不同的队列。所以如果是pdf,我们有一个pdf队列,一个ppt队列,一个doc队列和一个docx队列。

我们使用 Java 和 Octobot 作为连接到 MQ 的客户端。所以我们可以使用同一个 jar 文件,其中包含一个列出所有队列的 yml 文件。 JSON 具有任务名称。它在发送到队列中的每个 json 消息中都是相同的。所以同一个类在所有情况下都有效。

还注册了竞争消费者...我认为我们也这样做了..我们有多个运行 octobot(Java) 的服务器实例。所以这些被注册为 RabbitMQ 服务器上的消费者。 所以 RabbitMQ 根据收到的最后一个 ack 来决定哪个是空闲的,并相应地发送消息。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2017-12-22
    • 1970-01-01
    • 2014-05-24
    相关资源
    最近更新 更多