| 概念 | 角色 | 類比 | 關鍵特性 |
Producer (生產者) | 發送消息 | 寄信人 | 不直接投遞給 Queue,而是發給 Exchange |
Exchange (交換器) | 路由規則引擎 | 郵局分揀中心 | 四大類型:Direct/Topic/Fanout/Headers |
Queue (隊列) | 消息緩存 | 信箱 | 持久化、TTL、死信隊列、優先級 |
Binding (綁定) | Exchange→Queue 規則 | 投遞路徑 | Routing Key 匹配規則 |
Consumer (消費者) | 接收處理消息 | 收信人 | ACK 機制、預取數量、公平分發 |
| Broker | MQ 服務節點 | 郵政系統 | 叢集、高可用、鏡像隊列 |
關鍵點:Producer/Consumer/Broker 通常部署在不同機器,解耦合生產與消費速率,提供緩衝、削峰填谷能力。
3. HelloWorld:最簡單的點對點模型
場景:一個生產者發送,一個消費者接收,使用預設 Exchange (空字串,Direct 類型),Routing Key = Queue Name。
3.1 生產者
public class Send {
private static final String QUEUE_NAME = "hello";
public static void main(String[] args) throws Exception {
// 1. 連線工廠
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
factory.setUsername("guest");
factory.setPassword("guest");
// factory.setVirtualHost("/"); // 預設 vhost
// 2. 建立連線與通道
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
// 3. 宣告隊列(冪等:不存在則建立)
// durable=false: 非持久化,僅測試用
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 4. 發送消息
String message = "Hello World! " + LocalDateTime.now();
// exchange="": 預設直連交換器
// routingKey=QUEUE_NAME: 直接路由到同名隊列
channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
System.out.println(" [x] Sent: " + message);
} // try-with-resources 自動關閉 channel/connection
}
}
3.2 消費者
public class Recv {
private static final String QUEUE_NAME = "hello";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setUsername("guest");
factory.setPassword("guest");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
// 防止消費者先啟動導致隊列不存在
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
// 推模式消費:DeliveryConsumer 內部使用阻塞隊列
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println(" [x] Received: " + message);
};
// autoAck=true: 自動確認(生產環境建議手動 ACK)
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});
// 主線程保持存活
Thread.currentThread().join();
}
}
}
4. 關鍵細節補充
| 細節 | 說明 | 生產建議 |
| 隊列宣告冪等 | 多次宣告同名隊列參數一致不報錯 | 生產者/消費者皆宣告,防止啟動順序問題 |
| 消息體為 byte[] | 支援任意二進制數據(JSON/Protobuf/圖片) | 統一 UTF-8 字串或 Protobuf 序列化 |
| autoAck 風險 | true: 消息送達即標記刪除,消費者崩潰導致丟失 | 生產必須手動 ACK:basicAck/basicNack/requeue |
| 連線/通道管理 | Connection 昂貴(TCP 連線),Channel 輕量 | 連線池化、單連線多通道、心跳檢測 |
| 預設 Exchange | 名稱為空字串,Direct 類型,自動綁定所有隊列 RK=QueueName | 簡單場景直接用,複雜路由顯式宣告 Exchange |
5. 進階學習路線
- Exchange 類型:Direct/Topic/Fanout/Headers 路由規則實戰
- 可靠性:發布確認、消費者手動 ACK、事務消息、死信隊列、重試機制
- 高可用:鏡像隊列、Quorum Queues (3.8+)、叢集模式
- 效能調優:預取數量、懶加載隊列、流控、連線池
- Spring 整合:Spring AMQP、RabbitTemplate、@RabbitListener、容器管理
總結:RabbitMQ 以 Erlang 架構提供高併發、高可靠消息傳遞。入門關鍵在於理解 Exchange-Queue-Binding 路由模型、掌握連線/通道生命週期、區分自動/手動 ACK 機制。從 HelloWorld 起步,逐步掌握路由模式、可靠性保障、叢集架構,即可應對生產級異步解耦、削峰填谷、事件驅動架構需求。
- 上一篇文章: Spring AOP 實戰:Service 層日誌攔截、異常統一處理、執行時間監控完整方案
- 下一篇文章: 遊戲伺服器全局唯一 ID 生成方案對比:UUID、Redis、Flicker、Snowflake 及自定義改進版
Copyright ©
程式碼之家 All Rights Reserved