一、RabbitMQ的基本結構、角色和訊息模型
MQ的基本結構:
RabbitMQ中的一些角色:
- publisher:生產者
- consumer:消費者
- exchange個:交換機,負責訊息路由
- queue:佇列,儲存訊息
- virtualHost:虛擬主機,隔離不同租戶的exchange、queue、訊息的隔離
RabbitMQ官方提供了5個不同的Demo示例,對應了不同的訊息模型:
1.Basic Queue(基本訊息佇列) 簡單佇列模型 簡單模式:在這種模式下,生產者將訊息傳送到佇列,消費者監聽佇列並消費訊息。訊息被消費後,會自動從佇列中刪除。這種模式的優點是簡單易懂,但缺點是如果消費者處理訊息的速度慢,可能會導致訊息處理不及時。
2.Work queues(工作訊息佇列) ,也被稱為(Task queues),任務模型。簡單來說就是讓多個消費者繫結到一個佇列,共同消費佇列中的訊息。 工作佇列模型 ,一個生產者將訊息分發給多個消費者。當訊息處理比較耗時的時候,可能生產訊息的速度會遠遠大於訊息的消費速度。長此以往,訊息就會堆積越來越多,無法及時處理。此時就可以使用work 模型,多個消費者共同處理訊息處理,速度就能大大提高了。工作模式:在這種模式下,多個消費者競爭同一個佇列中的訊息,誰先獲取到訊息誰就處理該訊息。這種模式適用於處理高併發的情況,但需要注意避免多個消費者處理同一訊息的問題。
釋出訂閱(Publish、 Subscribe) ,又根據交換機型別不同分為三種:
Exchange(交換機)只負責轉發訊息,不具備儲存訊息的能力,因此如果沒有任何佇列與Exchange繫結,或者沒有符合路由規則的佇列,那麼訊息會丟失!
3.Fanout Exchange(廣播)
釋出/訂閱模型 ,生產者釋出訊息,多個消費者同時收取
4.Topic Exchange(主題 )Topic型別的Exchange與Direct相比,都是可以根據RoutingKey把訊息路由到不同的佇列。只不過Topic型別Exchange可以讓佇列在繫結Routing key`的時候使用萬用字元!主題模式:主題模式是路由模式的一種變體,它使用萬用字元來匹配路由鍵,使得訊息可以傳送到多個佇列中。這種模式增加了訊息的靈活性,但也需要小心設計萬用字元規則以避免不必要的訊息匹配。
5.Direct Exchange(路由 )
路由模式:在這種模式下,生產者將訊息傳送到交換機,交換機根據路由鍵將訊息路由到特定的佇列中,只有繫結了相應路由鍵的佇列才能接收訊息。這種模式適用於需要根據不同業務場景處理不同訊息的情況。
二、入門案例 (基本訊息佇列)
簡單佇列模式的模型圖:
官方的HelloWorld是基於最基礎的訊息佇列模型來實現的,只包括三個角色:
- publisher:訊息釋出者,將訊息傳送到佇列queue
- queue:訊息佇列,負責接受並快取訊息
- consumer:訂閱佇列,處理佇列中的訊息
工程包括三部分:
- mq-demo:父工程,管理專案依賴
- publisher:訊息的傳送者
- consumer:訊息的消費者
基本訊息佇列的訊息傳送流程:
1. 建立connection
2. 建立channel
3. 利用channel宣告佇列
4. 利用channel向佇列傳送訊息
publisher程式碼如下:
import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import org.junit.Test; import java.io.IOException; import java.util.concurrent.TimeoutException; public class PublisherTest { @Test public void testSendMessage() throws IOException, TimeoutException { // 1.建立連線 ConnectionFactory factory = new ConnectionFactory(); // 1.1.設定連線引數,分別是:主機名、埠號、vhost、使用者名稱、密碼 factory.setHost("192.168.150.101"); factory.setPort(5672); factory.setVirtualHost("/"); factory.setUsername("rbmq"); factory.setPassword("123456"); // 1.2.建立連線 Connection connection = factory.newConnection(); // 2.建立通道Channel Channel channel = connection.createChannel(); // 3.建立佇列 String queueName = "simple.queue"; channel.queueDeclare(queueName, false, false, false, null); // 4.傳送訊息 String message = "hello, rabbitmq!"; channel.basicPublish("", queueName, null, message.getBytes()); System.out.println("傳送訊息成功:【" + message + "】"); // 5.關閉通道和連線 channel.close(); connection.close(); } }
基本訊息佇列的訊息接收流程:
1. 建立connection
2. 建立channel
3. 利用channel宣告佇列
4. 定義consumer的消費行為handleDelivery()
5. 利用channel將消費者與佇列繫結
consumer程式碼如下:
import com.rabbitmq.client.*; import java.io.IOException; import java.util.concurrent.TimeoutException; public class ConsumerTest { public static void main(String[] args) throws IOException, TimeoutException { // 1.建立連線 ConnectionFactory factory = new ConnectionFactory(); // 1.1.設定連線引數,分別是:主機名、埠號、vhost、使用者名稱、密碼 factory.setHost("192.168.150.101"); factory.setPort(5672); factory.setVirtualHost("/"); factory.setUsername("rbmq"); factory.setPassword("123456"); // 1.2.建立連線 Connection connection = factory.newConnection(); // 2.建立通道Channel Channel channel = connection.createChannel(); // 3.建立佇列 String queueName = "simple.queue"; channel.queueDeclare(queueName, false, false, false, null); // 4.訂閱訊息 channel.basicConsume(queueName, true, new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { // 5.處理訊息 String message = new String(body); System.out.println("接收到訊息:【" + message + "】"); } }); System.out.println("等待接收訊息。。。。"); } }
演示測試成功。