是否可以让Java监听多个RabbitMQ队列?

时间:2012-03-04 15:41:01

标签: java messaging rabbitmq

更新:我认为我的解释可能过于冗长所以我认为我想要做的一个简单的思考方式是:我有多个工作节点,我想将它们用于不同的任务(以及那些不同的任务)来自不同的队列)。目前我只知道如何使它们监听与单一类型的工作相关联的单个队列,但是我希望它们能够监听不同的队列,以便不同的工作出现在同一个节点集群可以处理它们。希望更清楚。


大家好, 我怀疑这是可能的,但我似乎无法弄明白该怎么做。我浏览了rabbitmq网站上的教程,他们非常乐于助人并做了我想要的事情,除了它没有显示如何在同一个程序中监听多个队列。

我的程序结构基本上是几个阶段。例如,阶段1收集了大量数据,然后阶段2处理它并将其加载到数据库中,阶段3分析它与其他数据等等。每个阶段都无法启动直到前一阶段完成并且我想使用队列系统来使用多台机器来更快地完成每个阶段(因此所有消费者都在阶段1上工作,然后一旦完成所有阶段,他们就会一起完成第二阶段等)。

我想我不能只做一次每个阶段,因为队列可能是空的,计算机将移动到下一个队列,我无法知道它是否为空,因为所有工作都已完成或是否已完成,因为我们还没有开始将工作放入队列中。所以我想(如果我错了,请纠正我)更好的方法是听取与所有阶段相关的所有队列,并且当工作被放入phase1Queue时,它会对它起作用,如果工作被放入phase2Queue,它就会立即工作(我在流程之外有另外一个流程,我正在描述每个阶段完成时的监控,并为下一阶段设置)。希望这是有道理的。

队列示例中的代码对于听取一个队列的消费者很有帮助但是如何让它听多个(并根据不同的队列调用不同的程序)。如果有一个功能已经很好,那么我有点想找到我可以用来在java中实现这个的逻辑(最坏的情况我想过运行5个sperate程序来监听每个队列但是我试图找出来如果有更好的方法,让一个应用程序完成我的所有工作将使管理分发变得更容易。

谢谢!

P.S。如果它有帮助,这里的消费者代码适用于rabbitmq(但你可以看到它只定义了一个队列):

import java.io.IOException;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;

public class Worker {

  private static final String TASK_QUEUE_NAME = "task_queue";

  public static void main(String[] argv)
                      throws java.io.IOException,
                      java.lang.InterruptedException {

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

    channel.basicQos(1);

    QueueingConsumer consumer = new QueueingConsumer(channel);
    channel.basicConsume(TASK_QUEUE_NAME, false, consumer);

    while (true) {
      QueueingConsumer.Delivery delivery = consumer.nextDelivery();
      String message = new String(delivery.getBody());

      System.out.println(" [x] Received '" + message + "'");   
      doWork(message); 
      System.out.println(" [x] Done" );

      channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    }
  }
  //...
}

更新:根据评论,协调员流程非常简单。它只是一个从Phase1Queue监视的程序,一旦该队列为空,它只是启动一个进程来填充Phase2Queue等。

1 个答案:

答案 0 :(得分:1)

另一种方法是将不同阶段分成不同的模块/服务/流程,并使所有阶段同时运行。

每个阶段的消费者都会侦听不同的队列。每个阶段负责为下一阶段的队列生成消息。

通过这种方式,您可以通过单一职责降低复杂性。每个进程都从特定队列中消耗,并为另一个队列生成。如果需要,您可以向上和/或向外扩展这些单独的过程。

这是我们使用的模式。我们有一个初始工作,最终创建的子工作最多可达100倍。初始作业非常小且运行快,而子作业可能是长期运行的请求,我们使用少量云实例进行服务。然后,这些作业通过另一个队列返回结果,然后将其结果进行整理并添加到数据库中。

相关问题