RabbitMQ-路由模式

Anbang713發表於2018-09-28

一、簡介

上一篇我們提到《RabbitMQ-訂閱模式》從而實現了一個訊息被多個消費者消費,其大致原理是消費者1和消費者2都建立自己的佇列,然後將佇列繫結到交換機即可實現。

但是我們想象一下這樣的場景,比如我們有兩個系統,假設就叫做前臺系統和搜尋系統,那麼我們的後臺系統對某一商品進行增刪改查,就需求傳送訊息到前臺和搜尋系統。但是我們就在想,增刪改查四個操作到底哪些操作需求通知到不同的系統,比如新增商品,我們需要通知到搜尋系統,但是有必要通知到前臺系統嗎?

當然上面的場景可能有些不恰當,但為了做個說明並不為過,這個時候訂閱模式是不是就不滿足我們的需求了?因為我們需要將修改商品、刪除商品的訊息傳送到前臺和搜尋系統,但是新增商品只需要傳送給搜尋系統,這就引出了我們今天要學習的路由模式,如下圖:

二、編碼實現

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_ROUTING, "direct");
    // 訊息內容
    String message = "Hello World!";
    // 傳送一個routingKey為delete的訊息
    channel.basicPublish(QueueUtil.EXCHANGE_NAME_ROUTING, "delete", 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_ROUTING1, false, false, false, null);
    // 繫結佇列到交換機,接收routingKey為update的訊息
    channel.queueBind(QueueUtil.QUEUE_NAME_ROUTING1, QueueUtil.EXCHANGE_NAME_ROUTING, "update");
    // 同一時刻伺服器只會發一條訊息給消費者
    channel.basicQos(1);
    // 定義佇列的消費者
    QueueingConsumer consumer = new QueueingConsumer(channel);
    // 監聽佇列,手動返回完成
    channel.basicConsume(QueueUtil.QUEUE_NAME_ROUTING1, 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_ROUTING2, false, false, false, null);
    // 繫結佇列到交換機
    channel.queueBind(QueueUtil.QUEUE_NAME_ROUTING2, QueueUtil.EXCHANGE_NAME_ROUTING, "delete");
    // 同一時刻伺服器只會發一條訊息給消費者
    channel.basicQos(1);
    // 定義佇列的消費者
    QueueingConsumer consumer = new QueueingConsumer(channel);
    // 監聽佇列,手動返回完成
    channel.basicConsume(QueueUtil.QUEUE_NAME_ROUTING2, 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);
    }
  }
}

三、測試

可以看到,一個routingKey為delete的訊息只會被消費者2消費。

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

相關文章