RabbitMQ優(yōu)異性
RabbitMQ發(fā)展到今天,被越來越多的人認(rèn)可,這和它在易用性、擴(kuò)展性、可靠性和高可用性等方面的卓著表現(xiàn)是分不開的。RabbitMQ的具體特點(diǎn)可以概括為以下幾點(diǎn)。
- 可靠性:RabbitMQ使用一些機(jī)制來保證可靠性,如持久化、傳輸確認(rèn)及發(fā)布確認(rèn)等。
- 靈活的路由:在消息進(jìn)入隊(duì)列之前,通過交換器來路由消息。對于典型的路由功能,RabbitMQ已經(jīng)提供了一些內(nèi)置的交換器來實(shí)現(xiàn)。針對更復(fù)雜的路由功能,可以將多個(gè)交換器綁定在一起,也可以通過插件機(jī)制來實(shí)現(xiàn)自己的交換器。
- 擴(kuò)展性:多個(gè)RabbitMQ節(jié)點(diǎn)可以組成一個(gè)集群,也可以根據(jù)實(shí)際業(yè)務(wù)情況動(dòng)態(tài)地?cái)U(kuò)展集群中節(jié)點(diǎn)。
- 高可用性:隊(duì)列可以在集群中的機(jī)器上設(shè)置鏡像,使得在部分節(jié)點(diǎn)出現(xiàn)問題的情況下隊(duì)列仍然可用。
- 多種協(xié)議:RabbitMQ除了原生支持AMQP協(xié)議,還支持STOMP、MQTT等多種消息中間件協(xié)議。
- 多語言客戶端:RabbitMQ幾乎支持所有常用語言,比如Java、Python、Ruby、PHP、C#、JavaScript等。
- 管理界面:RabbitMQ提供了一個(gè)易用的用戶界面,使得用戶可以監(jiān)控和管理消息、集群中的節(jié)點(diǎn)等。
- 插件機(jī)制:RabbitMQ提供了許多插件,以實(shí)現(xiàn)從多方面進(jìn)行擴(kuò)展,當(dāng)然也可以編寫自己的插件。
RabbitMQ常見名詞解釋
Broker: 服務(wù)節(jié)點(diǎn)。如下圖,Broker實(shí)際上是一個(gè)消息的中轉(zhuǎn)站,負(fù)責(zé)接收、存儲和轉(zhuǎn)發(fā)消息
Queue: 隊(duì)列。RabbitMQ的內(nèi)部對象,用于存儲消息。RabbitMQ的生產(chǎn)者生產(chǎn)消息并最終投遞到隊(duì)列中,消費(fèi)者可以從隊(duì)列中獲取消息并消費(fèi)。但是當(dāng)多個(gè)消費(fèi)者訂閱了同一個(gè)隊(duì)列后,此時(shí)隊(duì)列中的消息會被分?jǐn)?輪詢)給多個(gè)消費(fèi)者進(jìn)行處理,而非每個(gè)消費(fèi)者都會收到所有的消息。所以當(dāng)有廣播消費(fèi)的需求時(shí),建議在交換器層級進(jìn)行處理,生產(chǎn)多個(gè)隊(duì)列,而不是在隊(duì)列層級做廣播處理。
Exchange: 交換器。生產(chǎn)者將消息發(fā)送到Exchange(交換器,通常也可以用大寫的“X”來表示),由交換器將消息路由到一個(gè)或者多個(gè)隊(duì)列中。如果路由不到,或許會返回給生產(chǎn)者,或許直接丟棄。交換器由生產(chǎn)者聲明,并設(shè)置相關(guān)屬性(如交換機(jī)類型,是否持久化等)。
RoutingKey: 路由鍵。生產(chǎn)者將消息發(fā)給交換器的時(shí)候,消息一般會攜帶一個(gè)RoutingKey,用來指定這個(gè)消息的路由規(guī)則,而這個(gè)Routing Key需要與交換器類型和綁定鍵(BindingKey)聯(lián)合使用才能最終生效。在交換器類型和綁定鍵(BindingKey)固定的情況下,生產(chǎn)者可以在發(fā)送消息給交換器時(shí),通過指定RoutingKey來決定消息流向哪里。
BindingKey: 綁定鍵。當(dāng)BindingKey和RoutingKey相匹配時(shí),消息會被路由到對應(yīng)的隊(duì)列中。BindingKey并不是在所有的情況下都生效,它依賴于交換器類型,比如fanout類型的交換器就會無視BindingKey,而是將消息路由到所有綁定到該交換器的隊(duì)列中。
Binding: 綁定。RabbitMQ中通過綁定將交換器與隊(duì)列關(guān)聯(lián)起來,在綁定的時(shí)候一般會指定一個(gè)綁定鍵(BindingKey),這樣RabbitMQ就知道如何正確地將消息路由到隊(duì)列了。
Connection: 連接。無論是消息的生產(chǎn)者還是消費(fèi)者,都需要和RabbitMQ Broker建立起連接來,這個(gè)連接就是一條TCP連接。
Channel: 信道。信道可以看作是連接的子集,是一個(gè)建立在Connection上的虛擬連接??蛻舳嗽诮⑵餋onnection后可以創(chuàng)建一個(gè)AMQP信道,每個(gè)信道都會被指派一個(gè)唯一的ID,每條AMQP指令都是通過信道完成處理的。信道主要是用來解決TCP連接創(chuàng)建和銷毀太過耗費(fèi)資源的問題,當(dāng)出現(xiàn)請求高峰的時(shí)候,使用信道實(shí)現(xiàn)對TCP連接的復(fù)用可以有效降低性能瓶頸的到來。
RabbitMQ交換器類型
RabbitMQ交換器有以下幾種:
- fanout: 此類型交換器會將所有發(fā)送到該交換器的消息路由到與該交換器綁定的隊(duì)列中。主要用于廣播消息。
- direct:此類型交換器會將消息路由到BindingKey與RoutingKey完全匹配的隊(duì)列中。主要用于指定匹配。
- topic: 此類型的交換器可以看作是在direct的基礎(chǔ)上做的再次擴(kuò)展,由于嚴(yán)格的完全匹配在很多情況下不能完全滿足實(shí)際業(yè)務(wù)的需求,topic交換器支持做一定的模糊匹配,將消息按照模糊匹配的規(guī)則發(fā)送到對應(yīng)的隊(duì)列中。主要用于消息多發(fā)。
- RoutingKey應(yīng)為一個(gè)點(diǎn)號“.”分隔的字符串(被點(diǎn)號“.”分隔開的每一段獨(dú)立的字符串稱為一個(gè)單詞),如“com.rabbitmq.client”、“java.util.concurrent”、“com.hidden.client”
- BindingKey和RoutingKey一樣也是點(diǎn)號“.”分隔的字符串,但是BindingKey可以存在兩種特殊字符"*" 和 “#”做模糊匹配,其中 "*"可以匹配一個(gè)字詞,"#"可以用戶匹配任意(含0)個(gè)單詞。
- headers: 此類型交換器不依賴于RoutingKey和BindingKey的匹配規(guī)則來路由消息,而是依據(jù)發(fā)送消息內(nèi)容中的headers屬性進(jìn)行匹配。該header屬性是一組鍵值對,且在隊(duì)列和消息中同時(shí)存在,只有在隊(duì)列和消息中的header屬性(鍵值對)完全匹配的時(shí)候,該消息會被路由到該隊(duì)列中。性能較差,不常見,不常用。
- 自定義
RabbitMQ消息交換方法
生產(chǎn)者生產(chǎn)消息
- 生產(chǎn)者連接到RabbitMQ Broker,建立一個(gè)連接(Connection),開啟一個(gè)信道(Channel)。
- 生產(chǎn)者聲明一個(gè)交換器,并設(shè)置相關(guān)屬性,比如交換機(jī)類型、是否持久化等。
- 生產(chǎn)者聲明一個(gè)隊(duì)列并設(shè)置相關(guān)屬性,比如是否排他、是否持久化、是否自動(dòng)刪除等。
- 生產(chǎn)者通過路由鍵將交換器和隊(duì)列綁定起來。
- 生產(chǎn)者發(fā)送消息至RabbitMQ Broker,其中包含路由鍵、交換器等信息。
- 相應(yīng)的交換器根據(jù)接收到的路由鍵查找相匹配的隊(duì)列。
- 如果找到,則將從生產(chǎn)者發(fā)送過來的消息存入相應(yīng)的隊(duì)列中。
- 如果沒有找到,則根據(jù)生產(chǎn)者配置的屬性選擇丟棄還是回退給生產(chǎn)者。
- 關(guān)閉信道。
- 關(guān)閉連接。
消費(fèi)者消費(fèi)消息
- 消費(fèi)者連接到RabbitMQ Broker,建立一個(gè)連接(Connection),開啟一個(gè)信道(Channel)。
- 消費(fèi)者向RabbitMQ Broker請求消費(fèi)相應(yīng)隊(duì)列中的消息,可能會設(shè)置相應(yīng)的回調(diào)函數(shù),以及做一些準(zhǔn)備工作。
- 等待RabbitMQ Broker回應(yīng)并投遞相應(yīng)隊(duì)列中的消息,消費(fèi)者接收消息。
- 消費(fèi)者確認(rèn)(ack)接收到的消息。
- RabbitMQ從隊(duì)列中刪除相應(yīng)已經(jīng)被確認(rèn)的消息。
- 關(guān)閉信道。
- 關(guān)閉連接。