RabbitMQ 消息分发

RabbitMQ 消息分发


如果有一个消息队列,有两个消费者,两个队列会同时收到消息么?

请看官方文档:

https://www.rabbitmq.com/tutorials/tutorial-two-java.html

当RabbitMQ队列拥有多个消费者时候,队列将以轮询(round-roubin)的方式发送给消费者

每个消息只会发送给消费者表里的一个消费者

Round-robin dispatching

One of the advantages of using a Task Queue is the ability to easily parallelise work. If we are building up a backlog of work, we can just add more workers and that way, scale easily.

First, let's try to run two worker instances at the same time. They will both get messages from the queue, but how exactly? Let's see.

You need three consoles open. Two will run the worker program. These consoles will be our two consumers - C1 and C2.


测试代码:

一个生产者

/**
 * 类说明
 * 
 * <pre>
 * Modify Information:
 * Author        Date          Description
 * ============ =========== ============================
 * DELL          2018年3月7日    Create this file
 * </pre>
 * 
 */

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.MessageProperties;

public class NewTask {

  private static final String TASK_QUEUE_NAME = "task_queue";

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

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("192.168.145.129");
    factory.setPort(5672);
    factory.setUsername("root");
    factory.setPassword("root");
    factory.setVirtualHost("/");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);

    String message = getMessage(argv);

    channel.basicPublish( "", TASK_QUEUE_NAME,
            MessageProperties.BASIC,
            message.getBytes());
//    channel.basicPublish( "", TASK_QUEUE_NAME,
//            MessageProperties.PERSISTENT_TEXT_PLAIN,
//            message.getBytes());
    System.out.println(" [x] Sent '" + message + "'");

    channel.close();
    connection.close();
  }      
  //...
  private static String getMessage(String[] argv) {
      return new String("test xiaoming");
  }
}

两个消费者:

消费者1:

/**
 * 类说明
 * 
 * <pre>
 * Modify Information:
 * Author        Date          Description
 * ============ =========== ============================
 * DELL          2018年3月7日    Create this file
 * </pre>
 * 
 */

import com.rabbitmq.client.*;

import java.io.IOException;

public class Worker {
  private static final String TASK_QUEUE_NAME = "task_queue";

  public static void main(String[] argv) throws Exception {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("192.168.145.129");
    factory.setPort(5672);
    factory.setUsername("root");
    factory.setPassword("root");
    factory.setVirtualHost("/");
    final Connection connection = factory.newConnection();
    final 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);

    final Consumer consumer = new DefaultConsumer(channel) {
      @Override
      public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        String message = new String(body, "UTF-8");

        System.out.println(" [x] Received '" + message + "'");
        try {
          doWork(message);
        } finally {
          System.out.println(" [x] Done");
          channel.basicAck(envelope.getDeliveryTag(), false);
        }
      }
    };
    boolean autoAck = false;
    channel.basicConsume(TASK_QUEUE_NAME, autoAck, consumer);
  }

  private static void doWork(String task) {
    for (char ch : task.toCharArray()) {
      if (ch == '.') {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException _ignored) {
          Thread.currentThread().interrupt();
        }
      }
    }
  }
}

消费者2:

import com.rabbitmq.client.*;

import java.io.IOException;

public class Worker2 {
  private static final String TASK_QUEUE_NAME = "task_queue";

  public static void main(String[] argv) throws Exception {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("192.168.145.129");
    factory.setPort(5672);
    factory.setUsername("root");
    factory.setPassword("root");
    factory.setVirtualHost("/");
    final Connection connection = factory.newConnection();
    final 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);

    final Consumer consumer = new DefaultConsumer(channel) {
      @Override
      public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        String message = new String(body, "UTF-8");

        System.out.println(" [x] Received '" + message + "'");
        try {
          doWork(message);
        } finally {
          System.out.println(" [x] Done");
          channel.basicAck(envelope.getDeliveryTag(), false);
        }
      }
    };
    boolean autoAck = false;
    channel.basicConsume(TASK_QUEUE_NAME, autoAck, consumer);
  }

  private static void doWork(String task) {
    for (char ch : task.toCharArray()) {
      if (ch == '.') {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException _ignored) {
          Thread.currentThread().interrupt();
        }
      }
    }
  }
}


先将 worer2 work 都启动起来,

再启动newTask 发消息

查看Worker2 ,Worker 哪个收到消息,就可以知道了,其实是轮循的,一个接着一个的








猜你喜欢

转载自blog.csdn.net/wangming520liwei/article/details/80624224