RabbitMQ 運轉(zhuǎn)流程
一、生產(chǎn)者發(fā)送消息

架構(gòu)
1、生產(chǎn)者連接到 RabbitMQ Broker,建立一個連接(Connection),開啟一個信道(Channel)。
2、生產(chǎn)者聲明一個交換器,并設(shè)置相關(guān)屬性,比如交換機類型、是否持久化等。
3、生產(chǎn)者聲明一個隊列并設(shè)置相關(guān)屬性,比如是否排他、是否持久化、是否自動刪除等。
4、生產(chǎn)者通過路由鍵將交換器和隊列綁定起來。
5、生產(chǎn)者發(fā)送消息至 RabbitMQ Broker,其中包含路由鍵、交換器等信息。
6、相應(yīng)的交換器根據(jù)接收到的路由鍵查找相匹配的隊列。
7、如果找到,則將從生產(chǎn)者發(fā)送過來的消息存入相應(yīng)的隊列中。
8、如果沒有找到,則根據(jù)生產(chǎn)者配置的屬性選擇丟棄還是回退給生產(chǎn)者。
9、關(guān)閉信道。
10、關(guān)閉連接。
1.1 、簡潔版生產(chǎn)者代碼
Connection connection = factory.newConnection();//創(chuàng)建連接
Channel channel = connection.createChannel();//創(chuàng)建信道
String message = "Hello World!";
channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY,
MessageProperties.PERSISTENT_TEXT_PLAIN,
message.getBytes());
//關(guān)閉資源
channel.close();
connection.close();
二、消費者接收消息的過程
(1)消費者連接到 RabbitMQ Broker,建立一個連接(Connection),開啟一個信道(Channel)。
(2)消費者向 RabbitMQ Broker 請求消費相應(yīng)隊列中的消息,可能會設(shè)置相應(yīng)的回調(diào)函數(shù),
以及做一些準備工作。
(3)等待 RabbitMQ Broker 回應(yīng)并投遞相應(yīng)隊列中的消息,消費者接收消息。
(4)消費者確認(ack)接收到的消息。
(5)RabbitMQ 從隊列中刪除相應(yīng)已經(jīng)被確認的消息。
(6)關(guān)閉信道。
(7)關(guān)閉連接。
三、Connection 和 Channel
Connection 和 Channel。我們知道無論是生產(chǎn)者還是消費者,都需要和 RabbitMQ Broker 建立連接,這個連接就是一條 TCP 連接,也就是Connection。一旦 TCP 連接建立起來,客戶端緊接著可以創(chuàng)建一個 AMQP 信道(Channel),每個信道都會被指派一個唯一的 ID。信道是建立在 Connection 之上的虛擬連接,RabbitMQ 處理的每條 AMQP 指令都是通過信道完成的。

流轉(zhuǎn)
我們完全可以直接使用 Connection 就能完成信道的工作,為什么還要引入信道呢?試想這樣一個場景,一個應(yīng)用程序中有很多個線程需要從 RabbitMQ 中消費消息,或者生產(chǎn)消息,那么必然需要建立很多個 Connection,也就是許多個 TCP 連接。然而對于操作系統(tǒng)而言,建立和銷毀 TCP 連接是非常昂貴的開銷,如果遇到使用高峰,性能瓶頸也隨之顯現(xiàn)。 RabbitMQ 采用類似 NIO(Non-blocking I/O)的做法,選擇 TCP 連接復(fù)用,不僅可以減少性能開銷,同時也便于管理。
每個線程把持一個信道,所以信道復(fù)用了 Connection 的 TCP 連接。同時 RabbitMQ 可以確保每個線程的私密性,就像擁有獨立的連接一樣。當(dāng)每個信道的流量不是很大時,復(fù)用單一的Connection 可以在產(chǎn)生性能瓶頸的情況下有效地節(jié)省 TCP 連接資源。但是當(dāng)信道本身的流量很大時,這時候多個信道復(fù)用一個 Connection 就會產(chǎn)生性能瓶頸,進而使整體的流量被限制了。此時就需要開辟多個 Connection,將這些信道均攤到這些 Connection 中,至于這些相關(guān)的調(diào)優(yōu)策略需要根據(jù)業(yè)務(wù)自身的實際情況進行調(diào)節(jié)。