【RabbitMQ】——佇列模式(2)
本篇部落格接著上一篇介紹MQ的佇列模式。
訂閱模式
P:生產者
c1、c2:消費者
紅色:訊息佇列
x:交換機
這種模式猛地一看和Work模式很像,但是這個模式中的每個消費者都有自己的佇列,同時引入了一個新的概念——交換機。
互動機分別繫結生產者和訊息佇列,生產者傳送的訊息會經過交換機到達佇列,這樣可以實現一個訊息被多個消費者獲取的目的。
注意:
如果交換機沒有繫結佇列,生產者傳送的訊息會丟失,因為互動機沒有儲存訊息的能力,訊息只能存在佇列之中。
生產者程式碼:
消費者一程式碼:
消費者二程式碼:
以上消費者一和消費者二種分別宣告瞭自己的佇列,都繫結到了同一個在生成者端宣告的交換機中。
生產者傳送一條訊息到交換機,繫結到了交換機的佇列都可以獲得這條訊息,實現一條訊息被多個消費者獲得的功能。
在RabbitMQ的管理工具中可以檢視繫結到交換機的佇列,如下:
路由模式
路由模式中的元素和訂閱者模式中的元素一樣,但是路由模式是在訂閱者模式基礎上的升級。訂閱者模式中的佇列繫結了交換機後會接受生成者傳送的所有訊息,但是消費者可能並不想接受所有的訊息,路由模式可以實現訊息的訂製。
路由模式在生產者傳送訊息時會宣告一個key,消費者的佇列在繫結交換機是會表明自己接受什麼key值的訊息,下面來看一下程式碼:
消費者程式碼:
生產者傳送了兩條訊息,一條key為delete,另一條key為update。在消費者端,佇列繫結互動機時宣告瞭delete這個key,這樣當前消費者只會接受到delete訊息,不會接收到奧update訊息。
萬用字元模式
#:可以匹配一個或多個詞
*:只能匹配一個詞
例:
item.category.add,使用#寫為item.#即可匹配到,使用*則需寫為item.*.*
生產者程式碼:
消費者程式碼:
消費者端的的佇列在繫結交換機時只需要寫item.#即可匹配到item.delete和item.update。
小結
通配模式——Topic
訂閱模式
c1、c2:消費者
紅色:訊息佇列
x:交換機
這種模式猛地一看和Work模式很像,但是這個模式中的每個消費者都有自己的佇列,同時引入了一個新的概念——交換機。
互動機分別繫結生產者和訊息佇列,生產者傳送的訊息會經過交換機到達佇列,這樣可以實現一個訊息被多個消費者獲取的目的。
注意:
如果交換機沒有繫結佇列,生產者傳送的訊息會丟失,因為互動機沒有儲存訊息的能力,訊息只能存在佇列之中。
生產者程式碼:
public class Send {
private final static String EXCHANGE_NAME = "test_exchange_fanout";
public static void main(String[] argv) throws Exception {
// 獲取到連線以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 宣告交換機(exchange)
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String message = "Hello World"; // 訊息內容
// 將訊息傳送到交換機
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
channel.close();
connection.close();
}
}
消費者一程式碼:
public class Recv {
private final static String QUEUE_NAME = "test_queue_fanout_1";
private final static String EXCHANGE_NAME = "test_exchange_fanout";
public static void main(String[] argv) throws Exception {
// 獲取到連線以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 宣告佇列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 繫結佇列到交換機
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
// 同一時刻伺服器只會發一條訊息給消費者
channel.basicQos(1);
// 定義佇列的消費者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 監聽佇列,手動返回完成
channel.basicConsume(QUEUE_NAME, false, consumer);
// 獲取訊息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" 前臺系統: '" + message + "'");
Thread.sleep(10);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
消費者二程式碼:
public class Recv2 {
private final static String QUEUE_NAME = "test_queue_fanout_2";
private final static String EXCHANGE_NAME = "test_exchange_fanout";
public static void main(String[] argv) throws Exception {
// 獲取到連線以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 宣告佇列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 繫結佇列到交換機
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
// 同一時刻伺服器只會發一條訊息給消費者
channel.basicQos(1);
// 定義佇列的消費者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 監聽佇列,手動返回完成
channel.basicConsume(QUEUE_NAME, false, consumer);
// 獲取訊息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" 搜尋系統: '" + message + "'");
Thread.sleep(10);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
以上消費者一和消費者二種分別宣告瞭自己的佇列,都繫結到了同一個在生成者端宣告的交換機中。
生產者傳送一條訊息到交換機,繫結到了交換機的佇列都可以獲得這條訊息,實現一條訊息被多個消費者獲得的功能。
在RabbitMQ的管理工具中可以檢視繫結到交換機的佇列,如下:
路由模式
路由模式中的元素和訂閱者模式中的元素一樣,但是路由模式是在訂閱者模式基礎上的升級。訂閱者模式中的佇列繫結了交換機後會接受生成者傳送的所有訊息,但是消費者可能並不想接受所有的訊息,路由模式可以實現訊息的訂製。
路由模式在生產者傳送訊息時會宣告一個key,消費者的佇列在繫結交換機是會表明自己接受什麼key值的訊息,下面來看一下程式碼:
生產者程式碼:
public class Send {
private final static String EXCHANGE_NAME = "test_exchange_direct";
public static void main(String[] argv) throws Exception {
// 獲取到連線以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 宣告exchange
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
// 訊息內容
String message1 = "刪除資訊, id = 1001";
String message2 = "更新資訊, id = 1002";
// 傳送訊息,宣告訊息的key
channel.basicPublish(EXCHANGE_NAME, "delete", null, message1.getBytes());
channel.basicPublish(EXCHANGE_NAME, "update", null, message2.getBytes());
System.out.println(" [x] Sent '" + message1 + "'");
System.out.println(" [x] Sent '" + message2 + "'");
channel.close();
connection.close();
}
}
消費者程式碼:
public class Recv {
private final static String QUEUE_NAME = "test_queue_direct_1";
private final static String EXCHANGE_NAME = "test_exchange_direct";
public static void main(String[] argv) throws Exception {
// 獲取到連線以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 宣告佇列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 繫結佇列到交換機,宣告接受訊息的key
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "delete");
// 同一時刻伺服器只會發一條訊息給消費者
channel.basicQos(1);
// 定義佇列的消費者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 監聽佇列,手動返回完成
channel.basicConsume(QUEUE_NAME, false, consumer);
// 獲取訊息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" 前臺系統: '" + message + "'");
Thread.sleep(10);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
生產者傳送了兩條訊息,一條key為delete,另一條key為update。在消費者端,佇列繫結互動機時宣告瞭delete這個key,這樣當前消費者只會接受到delete訊息,不會接收到奧update訊息。
萬用字元模式
萬用字元模式中的元素和訂閱者模式及路由模式中的元素一樣,而萬用字元模式是在路由模式基礎上的升級。路由模式需要消費者端的佇列在繫結交換機時宣告完整的key,如果需要接受多個key的訊息則需要繫結多條。萬用字元模式就類似模糊匹配,只需要宣告部分關鍵字即可。
#:可以匹配一個或多個詞
*:只能匹配一個詞
例:
item.category.add,使用#寫為item.#即可匹配到,使用*則需寫為item.*.*
生產者程式碼:
public class Send {
private final static String EXCHANGE_NAME = "test_exchange_topic";
public static void main(String[] argv) throws Exception {
// 獲取到連線以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 宣告exchange
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
// 訊息內容
String message1 = "刪除,id = 1001";
String message2 = "更新,id = 1002";
channel.basicPublish(EXCHANGE_NAME, "item.delete", null, message1.getBytes());
channel.basicPublish(EXCHANGE_NAME, "item.update", null, message2.getBytes());
System.out.println(" [x] Sent '" + message1 + "'");
System.out.println(" [x] Sent '" + message2 + "'");
channel.close();
connection.close();
}
}
消費者程式碼:
public class Recv2 {
private final static String QUEUE_NAME = "test_queue_topic_2";
private final static String EXCHANGE_NAME = "test_exchange_topic";
public static void main(String[] argv) throws Exception {
// 獲取到連線以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 宣告佇列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 繫結佇列到交換機
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "item.#");
// 同一時刻伺服器只會發一條訊息給消費者
channel.basicQos(1);
// 定義佇列的消費者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 監聽佇列,手動返回完成
channel.basicConsume(QUEUE_NAME, false, consumer);
// 獲取訊息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" 搜尋系統: '" + message + "'");
Thread.sleep(10);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
消費者端的的佇列在繫結交換機時只需要寫item.#即可匹配到item.delete和item.update。
小結
本篇文章中的三種訊息佇列包含的元素相同,功能是越來越靈活的,之所以能實現這種效果,是因為交換機有不同的模式,三種模式的生產者端在宣告交換機時分別使用了不同的模式。
訂閱模式——Fanout
路由模式——Direct通配模式——Topic
相關文章
- RabbitMQ六種佇列模式-路由模式MQ佇列模式路由
- RabbitMQ的佇列模式你真的懂嗎MQ佇列模式
- RabbitMQ 訊息佇列之佇列模型MQ佇列模型
- Laravel RabbitMQ 工作佇列LaravelMQ佇列
- RabbitMQ訊息佇列MQ佇列
- 延時佇列(RabbitMQ)佇列MQ
- [訊息佇列]RabbitMQ佇列MQ
- MQ訊息佇列_RabbitMQMQ佇列
- RabbitMQ 高階 - 死信佇列MQ佇列
- RabbitMQ:偽延時佇列MQ佇列
- rabbitmq訊息佇列原理MQ佇列
- RabbitMQ-簡單佇列MQ佇列
- 訊息佇列之RabbitMQ佇列MQ
- lumen 8.0 使用 rabbitmq 佇列MQ佇列
- 訊息佇列之 RabbitMQ佇列MQ
- RabbitMQ 入門 - 工作佇列MQ佇列
- 佇列工廠之RabbitMQ佇列MQ
- RabbitMQ 訊息佇列 配置MQ佇列
- Springboot + rabbitMq佇列Spring BootMQ佇列
- 處理線上RabbitMQ佇列阻塞MQ佇列
- RabbitMQ實戰《延遲佇列》MQ佇列
- 《RabbitMQ》什麼是死信佇列MQ佇列
- RabbitMQ實現延遲佇列MQ佇列
- RabbitMQ 實現延遲佇列MQ佇列
- RabbitMQ 高可用之映象佇列MQ佇列
- RabbitMQ延時佇列的使用MQ佇列
- RabbitMQ的工作佇列和路由MQ佇列路由
- RabbitMQ 佇列使用基礎教程MQ佇列
- netcore下RabbitMQ佇列、死信佇列、延時佇列及小應用NetCoreMQ佇列
- RabbitMQ訊息佇列系列教程(一)認識RabbitMQMQ佇列
- 訊息佇列-一篇讀懂rabbitmq(生命週期,confirm模式,延遲佇列,叢集)佇列MQ模式
- 使用 RabbitMQ 實現延時佇列MQ佇列
- Golang 實現 RabbitMQ 的死信佇列GolangMQ佇列
- RabbitMQ 訊息佇列之 Exchange TypesMQ佇列
- RabbitMQ訊息佇列(二):”Hello, World“MQ佇列
- 【RabbitMQ】一文帶你搞定RabbitMQ延遲佇列MQ佇列
- RabbitMQ .NET訊息佇列使用入門(五)【RabbitMQ例子】MQ佇列
- SpringBoot:初探 RabbitMQ 訊息佇列Spring BootMQ佇列