RabbitMQ歷史
RabbitMQ消息系統是一個由erlang開發的AMQP(Advanced Message Queue )的開源實現。在同步消息通訊的世界里有很多公開標准(如COBAR的IIOP,或者是SOAP等),但是在異步消息處理中卻不是這樣,只有大企業有一些商業實現(如微軟的MSMQ ,IBM的Websphere MQ等),因此,在2006年的6月,Cisco 、Redhat、iMatix 等聯合制定了AMQP的公開標准。
RabbitMQ是由RabbitMQ Technologies Ltd開發並且提供商業支持的。該公司在2010年4月被SpringSource(VMWare的一個部門)收購。在2013年5月被並入Pivotal。其實VMWare,Pivotal和EMC本質上是一家的。不同的是VMWare是獨立上市子公司,而Pivotal是整合了EMC的某些資源,現在並沒有上市。
RabbitMQ能為你做些什么?
言歸正傳,RabbitMQ,或者說AMQP解決了什么問題,或者說它的應用場景是什么?
消息系統允許軟件應用相互連接和擴展,這些應用可以相互鏈接起來組成一個更大的應用,或者將用戶設備和數據進行連接。消息系統通過將消息的發送和接收分離來實現應用程序的異步和解偶。或許你正在考慮進行數據投遞,非阻塞操作或推送通知。或許你想要實現發布/訂閱,異步處理,或者工作隊列。所有這些都屬於消息系統的模式。RabbitMQ是一個消息代理,一個消息系統的媒介。它可以為你的應用提供一個通用的消息發送和接收平台,並且保證消息再傳輸過程中的安全。
對於一個大型的軟件系統來說,它會有很多的組件或者說模塊或者說子系統。那么這些模塊的如何通信?這和傳統的IPC有很大的區別。傳統的IPC很多都是在單一系統上的,模塊耦合性很大,不適合擴展(Scalability);如果使用socket那么不同的模塊的確可以部署到不同的機器上,但是還是有很多問題需要解決。比如:
1)信息的發送者和接收者如何維持這個連接,如果一方的連接中斷,這期間的數據如何方式丟失?
2)如何降低發送者和接收者的耦合度?
3)如何讓Priority高的接收者先接到數據?
4)如何做到load balance?有效均衡接收者的負載?
5)如何有效的將數據發送到相關的接收者?也就是說將接收者subscribe 不同的數據,如何做有效的filter。
6)如何做到可擴展,甚至將這個通信模塊發到cluster上?
7)如何保證接收者接收到了完整,正確的數據?
AMDQ協議解決了以上的問題,而RabbitMQ實現了AMQP。
Rabbitmq工作模式
如上圖:
RabbitMQ Server
是一種傳輸服務,它的角色就是維護一條從Producer(生產者)到Consumer(消費者)的路線,保證數據能夠按照指定的方式進行傳輸。但是這個保證也不是100%的保證,但是對於普通的應用來說這已經足夠了。當然對於商業系統來說,可以再做一層數據一致性的防護,就可以徹底保證系統的一致性了。
Client A & B
也叫Producer(生產者),就是數據的發送方。一個Message(消息)有兩個部分:payload(有效載荷)和label(標簽)。payload顧名思義就是傳輸的數據。label是exchange的名字或者說是一個tag,它描述了payload,而且RabbitMQ也是通過這個label來決定把這個Message發給哪個Consumer(消費者)。AMQP僅僅描述了label,而RabbitMQ決定了如何使用這個label的規則。
Client 1 & 2 & 3
也叫Consumer(消費者),就是數據的接收方。把queue(隊列)比作是一個有名字的郵箱,當有Message到達某個郵箱后,RabbitMQ把它發送給它的某個訂閱者即Consumer。當然可能會把同一個Message發送給很多的Consumer。在這個Message中,只有payload,label已經被刪掉了。對於Consumer來說,它是不知道誰發送的這個信息的。就是協議本身不支持。但是當然了如果Producer發送的payload包含了Producer的信息就另當別論了。
對於一個數據從Producer到Consumer的正確傳遞,還有三個概念需要明確:exchanges, queues and bindings。
Exchanges – 是生產者發布消息的通道。
Queue – 是消費者接受消息的通道。
Bindings – 是將消息從交換路由綁定到特定隊列中的。
還有幾個概念是上述圖中沒有標明的,那就是Connection(連接),Channel(通道,頻道)。
Connection – 就是一個TCP的連接,Producer和Consumer都是通過TCP連接到RabbitMQ Server的。以后我們可以看到,程序的起始處就是建立這個TCP連接。
Channels – 虛擬連接,它建立在上述的TCP連接中。數據流動都是在Channel中進行的。也就是說,一般情況是程序起始建立TCP連接,第二步就是建立這個Channel。
那么,為什么使用Channel,而不是直接使用TCP連接?
對於OS來說,建立和關閉TCP連接是有代價的,頻繁的建立關閉TCP連接對於系統的性能有很大的影響,而且TCP的連接數也有限制,這也限制了系統處理高並發的能力。但是,在TCP連接中建立Channel是沒有上述代價的。對於Producer或者Consumer來說,可以並發的使用多個Channel進行Publish或者Receive。有實驗表明,1s的數據可以Publish10K的數據包。當然對於不同的硬件環境,不同的數據包大小這個數據肯定不一樣,但是我只想說明,對於普通的Consumer或者Producer來說,這已經足夠了。如果不夠用,你考慮的應該是如何細化split你的設計。
Rabbitmq技術亮點
1)可靠性
RabbitMQ提供了多種技術可以讓你在性能和可靠性之間進行權衡。這些技術包括持久性、投遞確認、發布者證實和高可用性。
2)靈活的路由
消息在到達隊列前是通過交換機進行路由的。RabbitMQ為典型的路由邏輯提供了多種內置交換機類型。如果你有更復雜的路由需求,可以將這些交換機組合起來使用,甚至你可以寫自己的交換機類型,並且當做RabbitMQ的插件來使用。
3)集群
在相同局域網中的多個RabbitMQ服務器可以被聚合在一起,作為一個獨立的邏輯代理來使用。
4)聯合
對於服務器來說,它比集群需要更多的松散和非可靠鏈接。為此RabbitMQ提供了聯合模型。
5)高可用的隊列
在同一個集群中,隊列可以被鏡像到多個機器中,以確保當其中某些硬件出現事故后,你的消息仍然是安全的。
6)多協議
RabbitMQ 支持多種消息協議中的消息傳遞。
7)廣泛的客戶端
只要是你能想到的語言幾乎都有與其相適配的RabbitMQ客戶端。
8)可視化管理工具
RabbitMQ附帶了一個易於使用的可視化管理工具,它可以幫助你監控消息代理的每一個環節。
9)追蹤
如果你的消息系統有異常行為,RabbitMQ還提供了追蹤的支持,讓你能夠發現問題所在。
10)插件系統
RabbitMQ附帶了各種各樣的插件來對自己進行擴展。甚至你也可以寫自己的插件來使用。
11)還有什么呢…
商業支持
可以提供商業支持,包括培訓和咨詢。
大型社區
圍繞着RabbitMQ有一個大型的社區,在那兒產生了各種各樣的客戶端、插件、指南等等。
關於RabbitMQ
RabbitMQ是使用Erlang開發的一個消息隊列,可以構建成集群,也可以單獨使用。
根據測試,RabbitMQ在不使用ACK機制的,Msg大小為1K的情況下,QPS可達6W+。再雙方ACK機制,Msg大小為1K的情況下,QPS瞬間降到了1W+。從某種意義上RabbitMQ還真是慢,但是我們需要思考下。
- 我們真的每個消息都能到1K嗎?
- 我們真的需要雙方都對消息ACK的系統嗎?
好了,如果兩個回答都是YES,那么RabbitMQ就是慢的。如果是No,那么RabbitMQ還是一個非常快的隊列。
RabbitMQ慢有幾個原因?
- RabbitMQ做為一個Broker,不單單做到了簡單的數據轉發功能,還保證了單個隊列上的數據有序,即便是有多個消費者和多個生產者。
- RabbitMQ的策略是實時轉發,而不像Kafka那樣等待刷盤之后才讓消費者來消費。
- 如果消費者和生產者不對等,會產生大量的磁盤IO操作,進行消息換出。
RabbitMQ為什么不好用?
- AMQP協議本身比較復雜,參數比較多。
- Erlang寫的,很多人不熟悉,並且Mnesia出現問題好多人解決不了。
RabbitMQ該怎么用?
- RabbitMQ的消息應當盡可能的小,並且只用來處理實時且要高可靠性的消息。
- 消費者和生產者的能力盡量對等,否則消息堆積會嚴重影響RabbitMQ的性能。
- 集群部署,使用熱備,保證消息的可靠性。
RabbitMQ 中文文檔