RabbitMQ-訂閱模式

Anbang713發表於2018-09-28

一、簡介

學習完《RabbitMQ-簡單佇列》和《RabbitMQ-Work模式》,今天我們一起學習訂閱模式。如下圖所示:

解讀:

1、1個生產者,多個消費者。

2、每一個消費者都有自己的一個佇列。

3、生產者沒有將訊息直接傳送到佇列,而是傳送到了交換機(x)。

4、每個佇列都要繫結到交換機。

5、生產者傳送的訊息,經過交換機到達佇列,實現一個訊息被多個消費者獲取的目的。

二、編碼實現

2.1、生產者

向交換機傳送訊息。(注意:訊息傳送到沒有佇列繫結的交換機時,訊息將丟失,因為交換機沒有儲存訊息的能力,訊息只能存在在佇列中。)

public class Producer {

  public static void main(String[] argv) throws Exception {
    // 獲取到連線以及mq通道
    Connection connection = ConnectionUtil.getConnection();
    Channel channel = connection.createChannel();
    // 宣告exchange
    channel.exchangeDeclare(QueueUtil.EXCHANGE_NAME_FANOUT, "fanout");
    // 訊息內容
    String message = "Hello World!";
    channel.basicPublish(QueueUtil.EXCHANGE_NAME_FANOUT, "", null, message.getBytes());
    channel.close();
    connection.close();
  }
}

2.2、消費者1

public class Receiver1 {

  public static void main(String[] argv) throws Exception {
    // 獲取到連線以及mq通道
    Connection connection = ConnectionUtil.getConnection();
    Channel channel = connection.createChannel();
    // 宣告佇列
    channel.queueDeclare(QueueUtil.QUEUE_NAME_FANOUT1, false, false, false, null);
    // 繫結佇列到交換機
    channel.queueBind(QueueUtil.QUEUE_NAME_FANOUT1, QueueUtil.EXCHANGE_NAME_FANOUT, "");
    // 同一時刻伺服器只會發一條訊息給消費者
    channel.basicQos(1);
    // 定義佇列的消費者
    QueueingConsumer consumer = new QueueingConsumer(channel);
    // 監聽佇列,手動返回完成
    channel.basicConsume(QueueUtil.QUEUE_NAME_FANOUT1, false, consumer);
    // 獲取訊息
    while (true) {
      QueueingConsumer.Delivery delivery = consumer.nextDelivery();
      String message = new String(delivery.getBody());
      System.out.println("Receiver1 Received:" + message);
      Thread.sleep(10);
      channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    }
  }
}

2.3、消費者2

public class Receiver2 {

  public static void main(String[] argv) throws Exception {
    // 獲取到連線以及mq通道
    Connection connection = ConnectionUtil.getConnection();
    Channel channel = connection.createChannel();
    // 宣告佇列
    channel.queueDeclare(QueueUtil.QUEUE_NAME_FANOUT2, false, false, false, null);
    // 繫結佇列到交換機
    channel.queueBind(QueueUtil.QUEUE_NAME_FANOUT2, QueueUtil.EXCHANGE_NAME_FANOUT, "");
    // 同一時刻伺服器只會發一條訊息給消費者
    channel.basicQos(1);
    // 定義佇列的消費者
    QueueingConsumer consumer = new QueueingConsumer(channel);
    // 監聽佇列,手動返回完成
    channel.basicConsume(QueueUtil.QUEUE_NAME_FANOUT2, false, consumer);
    // 獲取訊息
    while (true) {
      QueueingConsumer.Delivery delivery = consumer.nextDelivery();
      String message = new String(delivery.getBody());
      System.out.println("Receiver2 Received:" + message);
      Thread.sleep(10);
      channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    }
  }
}

三、測試

啟動消費者1和消費者2,我們在管理工具中檢視佇列和交換機的繫結關係:

 控制檯看是否有進行消費,可以看到該訊息被消費者1和消費者2消費了。

 

原始碼地址:https://gitee.com/chengab/RabbitMQ 

相關文章