概念
RabbitMQ是實現了高級消息隊列協議(AMQP)的開源消息代理軟件(亦稱面向消息的中間件)。RabbitMQ服務器是用Erlang語言編寫的,而集群和故障轉移是構建在開放電信平臺框架上的。所有主要的編程語言均有與代理接口通訊的客戶端庫。
RabbitMQ是一套開源(MPL)的消息隊列服務軟件,是由 LShift 提供的一個 Advanced Message Queuing Protocol (AMQP) 的開源實現,由以高性能、健壯以及可伸縮性出名的 Erlang 寫成。

AMQP
AMQP 其實和Http一樣 都是一種協議, 只不過 Http是針對網絡傳輸的, 而AMQP是基于消息隊列的
AMQP 協議中的基本概念
**Broker: **
接收和分發消息的應用,我們在介紹消息中間件的時候所說的消息系統就是Message Broker。
**Virtual host: **
出于多租戶和安全因素設計的,把AMQP的基本組件劃分到一個虛擬的分組中,類似于網絡中的namespace概念。當多個不同的用戶使用同一個RabbitMQ server提供的服務時,可以劃分出多個vhost,每個用戶在自己的vhost創建exchange/queue等。
「Connection:」
publisher/consumer和broker之間的TCP連接。斷開連接的操作只會在client端進行,Broker不會斷開連接,除非出現網絡故障或broker服務出現問題。
**Channel: **
如果每一次訪問RabbitMQ都建立一個Connection,在消息量大的時候建立TCP Connection的開銷將是巨大的,效率也較低。Channel是在connection內部建立的邏輯連接,如果應用程序支持多線程,通常每個thread創建單獨的channel進行通訊,AMQP method包含了channel id幫助客戶端和message broker識別channel,所以channel之間是完全隔離的。Channel作為輕量級的Connection極大減少了操作系統建立TCP connection的開銷。
「Exchange:」
message到達broker的第一站,根據分發規則,匹配查詢表中的routing key,分發消息到queue中去。常用的類型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast)。
**Queue: **
消息最終被送到這里等待consumer取走。一個message可以被同時拷貝到多個queue中。
「Binding:」
exchange和queue之間的虛擬連接,binding中可以包含routing key。Binding信息被保存到exchange中的查詢表中,用于message的分發依據。
Exchange的類型
「direct :」
這種類型的交換機的路由規則是根據一個routingKey的標識,交換機通過一個routingKey與隊列綁定 ,在生產者生產消息的時候 指定一個routingKey 當綁定的隊列的routingKey 與生產者發送的一樣 那么交換機會吧這個消息發送給對應的隊列。
「fanout:」
這種類型的交換機路由規則很簡單,只要與他綁定了的隊列, 他就會吧消息發送給對應隊列(與routingKey沒關系)
「topic:」
(因為*在這個筆記軟件里面是關鍵字,所以下面就用星替換掉了)這種類型的交換機路由規則也是和routingKey有關 只不過 topic他可以根據:星,#( 星號代表過濾一單詞,#代表過濾后面所有單詞, 用.隔開)來識別routingKey 我打個比方 假設 我綁定的routingKey 有隊列A和B A的routingKey是:星.user B的routingKey是: #.user
那么我生產一條消息routingKey 為:error.user 那么此時 2個隊列都能接受到, 如果改為 topic.error.user 那么這時候 只有B能接受到了
「headers:」
這個類型的交換機很少用到,他的路由規則 與routingKey無關 而是通過判斷header參數來識別的, 基本上沒有應用場景,因為上面的三種類型已經能應付了。
執行過程
1.客戶端連接到消息隊列服務器,打開一個Channel。
2.客戶端聲明一個Exchange,并設置相關屬性。
3.客戶端聲明一個Queue,并設置相關屬性。
4.客戶端使用Routing key,在Exchange和Queue之間建立好綁定關系。
5.客戶端投遞消息到Exchange。
Exchange接收到消息后,就根據消息的key和已經設置的Binding,進行消息路由,將消息投遞到一個或多個隊列里。有三種類型的Exchanges:direct,fanout,topic,每個實現了不同的路由算法:
消息的ack機制
默認情況下,如果Message 已經被某個Consumer正確的接收到了,那么該Message就會被從queue中移除。當然也可以讓同一個Message發送到很多的Consumer。
如果一個queue沒被任何的Consumer Subscribe(訂閱),那么,如果這個queue有數據到達,那么這個數據會被cache,不會被丟棄。當有Consumer時,這個數據會被立即發送到這個Consumer,這個數據被Consumer正確收到時,這個數據就被從queue中刪除。
消息持久化
RabbitMQ支持消息的持久化,也就是數據寫在磁盤上,為了數據安全考慮,大多數用戶都會選擇持久化。消息隊列持久化包括3個部分:
1.Exchange持久化,在聲明時指定durable => 1
2.Queue持久化,在聲明時指定durable => 1
3.消息持久化,在投遞時指定delivery_mode => 2(1是非持久化)
若Exchange和Queue都是持久化的,那么它們之間的Binding也是持久化的;而Exchange和Queue兩者之間有一個持久化,一個非持久化,就不允許建立綁定。
特性
可伸縮性:集群服務
消息持久化:從內存持久化消息到硬盤,再從硬盤加載到內存
支持的操作系統
1、Linux
2、WindowsNT到10
3、VxWorks
4、macOS
5、FreeBSD
6、Windows Server2003到2016
7、Solaris
8、TRU64
支持的編程語言
1、Swift
2、Java
3、Elixir
4、Python
5、JavaScript
6、Objective-C
7、Go
8、Ruby
9、C#
7、Ruby
8、PHP
使用場景
解耦(為面向服務的架構(SOA)提供基本的最終一致性實現)
異步提升效率
流量削峰,流量削峰也是消息隊列中的常用場景,一般在秒殺或團搶活動中使用廣泛
優缺點
在特殊場景下有其對應的好處,解耦、異步、削峰。
「缺點」
1、系統的可用性降低
系統引入的外部依賴越多,系統越容易掛掉。
2、系統的復雜性提高
引入了MQ之后,需要考慮的問題也變得多了,如何保證消息沒有重復消費?如何保證消息不丟失?怎么保證消息傳遞的順序?
3、一致性問題
A系統發送完消息直接返回成功,但是BCD系統之中若有系統寫庫失敗,則會產生數據不一致的問題。這就涉及到分布式事務的問題。