1. 歷史
RabbitMQ是一個(gè)由erlang開發(fā)的AMQP(Advanced Message Queue )的開源實(shí)現(xiàn)舔腾。AMQP 的出現(xiàn)其實(shí)也是應(yīng)了廣大人民群眾的需求间驮,雖然在同步消息通訊的世界里有很多公開標(biāo)準(zhǔn)(如 COBAR的 IIOP 零抬,或者是 SOAP 等)地回,但是在異步消息處理中卻不是這樣浙宜,只有大企業(yè)有一些商業(yè)實(shí)現(xiàn)(如微軟的 MSMQ ,IBM 的 Websphere MQ 等)酬荞,因此搓劫,在 2006 年的 6 月,Cisco 混巧、Redhat枪向、iMatix 等聯(lián)合制定了 AMQP 的公開標(biāo)準(zhǔn)。
RabbitMQ是由RabbitMQ Technologies Ltd開發(fā)并且提供商業(yè)支持的咧党。該公司在2010年4月被SpringSource(VMWare的一個(gè)部門)收購秘蛔。在2013年5月被并入Pivotal。其實(shí)VMWare傍衡,Pivotal和EMC本質(zhì)上是一家的深员。不同的是VMWare是獨(dú)立上市子公司,而Pivotal是整合了EMC的某些資源聪舒,現(xiàn)在并沒有上市辨液。
RabbitMQ的官網(wǎng)是http://www.rabbitmq.com
2. 應(yīng)用場景
言歸正傳虐急。RabbitMQ箱残,或者說AMQP解決了什么問題,或者說它的應(yīng)用場景是什么止吁?
對于一個(gè)大型的軟件系統(tǒng)來說被辑,它會有很多的組件或者說模塊或者說子系統(tǒng)或者(subsystem or Component or submodule)。那么這些模塊的如何通信敬惦?這和傳統(tǒng)的IPC有很大的區(qū)別盼理。傳統(tǒng)的IPC很多都是在單一系統(tǒng)上的,模塊耦合性很大俄删,不適合擴(kuò)展(Scalability)宏怔;如果使用socket那么不同的模塊的確可以部署到不同的機(jī)器上奏路,但是還是有很多問題需要解決。比如:
1)信息的發(fā)送者和接收者如何維持這個(gè)連接臊诊,如果一方的連接中斷鸽粉,這期間的數(shù)據(jù)如何方式丟失?
2)如何降低發(fā)送者和接收者的耦合度抓艳?
3)如何讓Priority高的接收者先接到數(shù)據(jù)触机?
4)如何做到load balance?有效均衡接收者的負(fù)載玷或?
5)如何有效的將數(shù)據(jù)發(fā)送到相關(guān)的接收者儡首?也就是說將接收者subscribe 不同的數(shù)據(jù),如何做有效的filter偏友。
6)如何做到可擴(kuò)展蔬胯,甚至將這個(gè)通信模塊發(fā)到cluster上?
7)如何保證接收者接收到了完整位他,正確的數(shù)據(jù)笔宿?
AMDQ協(xié)議解決了以上的問題,而RabbitMQ實(shí)現(xiàn)了AMQP棱诱。
3. 系統(tǒng)架構(gòu)
image.png
RabbitMQ Server:也叫broker server泼橘,它不是運(yùn)送食物的卡車,而是一種傳輸服務(wù)迈勋。原話是RabbitMQisn’t a food truck, it’s a delivery service. 他的角色就是維護(hù)一條從Producer到Consumer的路線炬灭,保證數(shù)據(jù)能夠按照指定的方式進(jìn)行傳輸。但是這個(gè)保證也不是100%的保證靡菇,但是對于普通的應(yīng)用來說這已經(jīng)足夠了重归。當(dāng)然對于商業(yè)系統(tǒng)來說,可以再做一層數(shù)據(jù)一致性的guard厦凤,就可以徹底保證系統(tǒng)的一致性了鼻吮。
Client P:也叫Producer,數(shù)據(jù)的發(fā)送方较鼓。createmessages and publish (send) them to a broker server (RabbitMQ).一個(gè)Message有兩個(gè)部分:payload(有效載荷)和label(標(biāo)簽)椎木。payload顧名思義就是傳輸?shù)臄?shù)據(jù)。label是exchange的名字或者說是一個(gè)tag博烂,它描述了payload香椎,而且RabbitMQ也是通過這個(gè)label來決定把這個(gè)Message發(fā)給哪個(gè)Consumer。AMQP僅僅描述了label禽篱,而RabbitMQ決定了如何使用這個(gè)label的規(guī)則畜伐。
Client C:也叫Consumer,數(shù)據(jù)的接收方躺率。Consumersattach to a broker server (RabbitMQ) and subscribe to a queue玛界。把queue比作是一個(gè)有名字的郵箱万矾。當(dāng)有Message到達(dá)某個(gè)郵箱后,RabbitMQ把它發(fā)送給它的某個(gè)訂閱者即Consumer慎框。當(dāng)然可能會把同一個(gè)Message發(fā)送給很多的Consumer勤众。在這個(gè)Message中,只有payload鲤脏,label已經(jīng)被刪掉了们颜。對于Consumer來說,它是不知道誰發(fā)送的這個(gè)信息的猎醇。就是協(xié)議本身不支持窥突。但是當(dāng)然了如果Producer發(fā)送的payload包含了Producer的信息就另當(dāng)別論了。
對于一個(gè)數(shù)據(jù)從Producer到Consumer的正確傳遞硫嘶,還有三個(gè)概念需要明確:exchanges, queues and bindings阻问。
Exchangesare where producers publish their messages.
Queuesare where the messages end up and are received by consumers
Bindingsare how the messages get routed from the exchange to particular queues.
還有幾個(gè)概念是上述圖中沒有標(biāo)明的,那就是Connection(連接)沦疾,Channel(通道称近,頻道)。
Connection:就是一個(gè)TCP的連接哮塞。Producer和Consumer都是通過TCP連接到RabbitMQ Server的刨秆。以后我們可以看到,程序的起始處就是建立這個(gè)TCP連接忆畅。
Channels:虛擬連接衡未。它建立在上述的TCP連接中。數(shù)據(jù)流動(dòng)都是在Channel中進(jìn)行的家凯。也就是說缓醋,一般情況是程序起始建立TCP連接,第二步就是建立這個(gè)Channel绊诲。
那么送粱,為什么使用Channel,而不是直接使用TCP連接掂之?
對于OS來說抗俄,建立和關(guān)閉TCP連接是有代價(jià)的,頻繁的建立關(guān)閉TCP連接對于系統(tǒng)的性能有很大的影響板惑,而且TCP的連接數(shù)也有限制橄镜,這也限制了系統(tǒng)處理高并發(fā)的能力。但是冯乘,在TCP連接中建立Channel是沒有上述代價(jià)的。對于Producer或者Consumer來說晒夹,可以并發(fā)的使用多個(gè)Channel進(jìn)行Publish或者Receive裆馒。有實(shí)驗(yàn)表明姊氓,1s的數(shù)據(jù)可以Publish10K的數(shù)據(jù)包。當(dāng)然對于不同的硬件環(huán)境喷好,不同的數(shù)據(jù)包大小這個(gè)數(shù)據(jù)肯定不一樣翔横,但是我只想說明,對于普通的Consumer或者Producer來說梗搅,這已經(jīng)足夠了禾唁。如果不夠用,你考慮的應(yīng)該是如何細(xì)化split你的設(shè)計(jì)无切。
Broker:簡單來說就是消息隊(duì)列服務(wù)器實(shí)體荡短。
Exchange:消息交換機(jī),它指定消息按什么規(guī)則哆键,路由到哪個(gè)隊(duì)列掘托。
Queue:消息隊(duì)列載體,每個(gè)消息都會被投入到一個(gè)或多個(gè)隊(duì)列籍嘹。
Binding:綁定闪盔,它的作用就是把exchange和queue按照路由規(guī)則綁定起來。
Routing Key:路由關(guān)鍵字辱士,exchange根據(jù)這個(gè)關(guān)鍵字進(jìn)行消息投遞泪掀。
vhost:虛擬主機(jī),一個(gè)broker里可以開設(shè)多個(gè)vhost颂碘,用作不同用戶的權(quán)限分離族淮。
producer:消息生產(chǎn)者,就是投遞消息的程序凭涂。
consumer:消息消費(fèi)者祝辣,就是接受消息的程序。
channel:消息通道切油,在客戶端的每個(gè)連接里蝙斜,可建立多個(gè)channel,每個(gè)channel代表一個(gè)會話任務(wù)澎胡。
由Exchange孕荠,Queue,RoutingKey三個(gè)才能決定一個(gè)從Exchange到Queue的唯一的線路攻谁。
4.基本概念
ConnectionFactory稚伍、Connection、Channel
ConnectionFactory戚宦、Connection个曙、Channel都是RabbitMQ對外提供的API中最基本的對象。Connection是RabbitMQ的socket鏈接受楼,它封裝了socket協(xié)議相關(guān)部分邏輯垦搬。ConnectionFactory為Connection的制造工廠呼寸。
Channel是我們與RabbitMQ打交道的最重要的一個(gè)接口,我們大部分的業(yè)務(wù)操作是在Channel這個(gè)接口中完成的猴贰,包括定義Queue对雪、定義Exchange、綁定Queue與Exchange米绕、發(fā)布消息等瑟捣。
Queue
Queue(隊(duì)列)是RabbitMQ的內(nèi)部對象,用于存儲消息栅干,用下圖表示迈套。
queue
image.png
RabbitMQ中的消息都只能存儲在Queue中,生產(chǎn)者(下圖中的P)生產(chǎn)消息并最終投遞到Queue中非驮,消費(fèi)者(下圖中的C)可以從Queue中獲取消息并消費(fèi)交汤。
image.png
多個(gè)消費(fèi)者可以訂閱同一個(gè)Queue,這時(shí)Queue中的消息會被平均分?jǐn)偨o多個(gè)消費(fèi)者進(jìn)行處理劫笙,而不是每個(gè)消費(fèi)者都收到所有的消息并處理芙扎。
image.png
Message acknowledgment
在實(shí)際應(yīng)用中,可能會發(fā)生消費(fèi)者收到Queue中的消息填大,但沒有處理完成就宕機(jī)(或出現(xiàn)其他意外)的情況戒洼,這種情況下就可能會導(dǎo)致消息丟失。為了避免這種情況發(fā)生允华,我們可以要求消費(fèi)者在消費(fèi)完消息后發(fā)送一個(gè)回執(zhí)給RabbitMQ掘譬,RabbitMQ收到消息回執(zhí)(Message acknowledgment)后才將該消息從Queue中移除削罩;如果RabbitMQ沒有收到回執(zhí)并檢測到消費(fèi)者的RabbitMQ連接斷開蛔六,則RabbitMQ會將該消息發(fā)送給其他消費(fèi)者(如果存在多個(gè)消費(fèi)者)進(jìn)行處理轴捎。這里不存在timeout概念,一個(gè)消費(fèi)者處理消息時(shí)間再長也不會導(dǎo)致該消息被發(fā)送給其他消費(fèi)者百炬,除非它的RabbitMQ連接斷開褐隆。
這里會產(chǎn)生另外一個(gè)問題,如果我們的開發(fā)人員在處理完業(yè)務(wù)邏輯后剖踊,忘記發(fā)送回執(zhí)給RabbitMQ庶弃,這將會導(dǎo)致嚴(yán)重的bug——Queue中堆積的消息會越來越多;消費(fèi)者重啟后會重復(fù)消費(fèi)這些消息并重復(fù)執(zhí)行業(yè)務(wù)邏輯德澈。
另外pub message是沒有ack的歇攻。
Message durability
如果我們希望即使在RabbitMQ服務(wù)重啟的情況下,也不會丟失消息梆造,我們可以將Queue與Message都設(shè)置為可持久化的(durable)缴守,這樣可以保證絕大部分情況下我們的RabbitMQ消息不會丟失。但依然解決不了小概率丟失事件的發(fā)生(比如RabbitMQ服務(wù)器已經(jīng)接收到生產(chǎn)者的消息,但還沒來得及持久化該消息時(shí)RabbitMQ服務(wù)器就斷電了)斧散,如果我們需要對這種小概率事件也要管理起來供常,那么我們要用到事務(wù)摊聋。由于這里僅為RabbitMQ的簡單介紹鸡捐,所以這里將不講解RabbitMQ相關(guān)的事務(wù)。
Prefetch count
前面我們講到如果有多個(gè)消費(fèi)者同時(shí)訂閱同一個(gè)Queue中的消息麻裁,Queue中的消息會被平攤給多個(gè)消費(fèi)者箍镜。這時(shí)如果每個(gè)消息的處理時(shí)間不同,就有可能會導(dǎo)致某些消費(fèi)者一直在忙煎源,而另外一些消費(fèi)者很快就處理完手頭工作并一直空閑的情況色迂。我們可以通過設(shè)置prefetchCount來限制Queue每次發(fā)送給每個(gè)消費(fèi)者的消息數(shù),比如我們設(shè)置prefetchCount=1手销,則Queue每次給每個(gè)消費(fèi)者發(fā)送一條消息歇僧;消費(fèi)者處理完這條消息后Queue會再給該消費(fèi)者發(fā)送一條消息。
image.png
Exchange
在上一節(jié)我們看到生產(chǎn)者將消息投遞到Queue中锋拖,實(shí)際上這在RabbitMQ中這種事情永遠(yuǎn)都不會發(fā)生诈悍。實(shí)際的情況是,生產(chǎn)者將消息發(fā)送到Exchange(交換器兽埃,下圖中的X)侥钳,由Exchange將消息路由到一個(gè)或多個(gè)Queue中(或者丟棄)。
image.png
Exchange是按照什么邏輯將消息路由到Queue的柄错?這個(gè)將在Binding一節(jié)介紹舷夺。
RabbitMQ中的Exchange有四種類型,不同的類型有著不同的路由策略售貌,這將在Exchange Types一節(jié)介紹给猾。
routing key
生產(chǎn)者在將消息發(fā)送給Exchange的時(shí)候,一般會指定一個(gè)routing key颂跨,來指定這個(gè)消息的路由規(guī)則敢伸,而這個(gè)routing key需要與Exchange Type及binding key聯(lián)合使用才能最終生效。
在Exchange Type與binding key固定的情況下(在正常使用時(shí)一般這些內(nèi)容都是固定配置好的)毫捣,我們的生產(chǎn)者就可以在發(fā)送消息給Exchange時(shí)详拙,通過指定routing key來決定消息流向哪里。
RabbitMQ為routing key設(shè)定的長度限制為255 bytes蔓同。
Binding
RabbitMQ中通過Binding將Exchange與Queue關(guān)聯(lián)起來饶辙,這樣RabbitMQ就知道如何正確地將消息路由到指定的Queue了。
image.png
Binding key
在綁定(Binding)Exchange與Queue的同時(shí)斑粱,一般會指定一個(gè)binding key弃揽;消費(fèi)者將消息發(fā)送給Exchange時(shí),一般會指定一個(gè)routing key;當(dāng)binding key與routing key相匹配時(shí)矿微,消息將會被路由到對應(yīng)的Queue中痕慢。這個(gè)將在Exchange Types章節(jié)會列舉實(shí)際的例子加以說明。
在綁定多個(gè)Queue到同一個(gè)Exchange的時(shí)候涌矢,這些Binding允許使用相同的binding key掖举。
binding key 并不是在所有情況下都生效,它依賴于Exchange Type娜庇,比如fanout類型的Exchange就會無視binding key塔次,而是將消息路由到所有綁定到該Exchange的Queue。
Exchange Types
RabbitMQ常用的Exchange Type有fanout名秀、direct励负、topic、headers這四種(AMQP規(guī)范里還提到兩種Exchange Type匕得,分別為system與自定義继榆,這里不予以描述),下面分別進(jìn)行介紹汁掠。
fanout
fanout類型的Exchange路由規(guī)則非常簡單略吨,它會把所有發(fā)送到該Exchange的消息路由到所有與它綁定的Queue中。
image.png
上圖中调塌,生產(chǎn)者(P)發(fā)送到Exchange(X)的所有消息都會路由到圖中的兩個(gè)Queue晋南,并最終被兩個(gè)消費(fèi)者(C1與C2)消費(fèi)。
direct
direct類型的Exchange路由規(guī)則也很簡單羔砾,它會把消息路由到那些binding key與routing key完全匹配的Queue中负间。
image.png
以上圖的配置為例,我們以routingKey=”error”發(fā)送消息到Exchange姜凄,則消息會路由到Queue1(amqp.gen-S9b…政溃,這是由RabbitMQ自動(dòng)生成的Queue名稱)和Queue2(amqp.gen-Agl…);如果我們以routingKey=”info”或routingKey=”warning”來發(fā)送消息态秧,則消息只會路由到Queue2董虱。如果我們以其他routingKey發(fā)送消息,則消息不會路由到這兩個(gè)Queue中申鱼。
topic
前面講到direct類型的Exchange路由規(guī)則是完全匹配binding key與routing key愤诱,但這種嚴(yán)格的匹配方式在很多情況下不能滿足實(shí)際業(yè)務(wù)需求。topic類型的Exchange在匹配規(guī)則上進(jìn)行了擴(kuò)展捐友,它與direct類型的Exchage相似淫半,也是將消息路由到binding key與routing key相匹配的Queue中,但這里的匹配規(guī)則有些不同匣砖,它約定:
routing key為一個(gè)句點(diǎn)號“.”分隔的字符串(我們將被句點(diǎn)號“. ”分隔開的每一段獨(dú)立的字符串稱為一個(gè)單詞)科吭,如“stock.usd.nyse”昏滴、“nyse.vmw”、“quick.orange.rabbit” binding key與routing key一樣也是句點(diǎn)號“. ”分隔的字符串
binding key中可以存在兩種特殊字符“*”與“#”对人,用于做模糊匹配谣殊,其中“*”用于匹配一個(gè)單詞,“#”用于匹配多個(gè)單詞(可以是零個(gè))
image.png
以上圖中的配置為例牺弄,routingKey=”quick.orange.rabbit”的消息會同時(shí)路由到Q1與Q2姻几,routingKey=”lazy.orange.fox”的消息會路由到Q1,routingKey=”lazy.brown.fox”的消息會路由到Q2猖闪,routingKey=”lazy.pink.rabbit”的消息會路由到Q2(只會投遞給Q2一次鲜棠,雖然這個(gè)routingKey與Q2的兩個(gè)bindingKey都匹配)肌厨;routingKey=”quick.brown.fox”培慌、routingKey=”orange”、routingKey=”quick.orange.male.rabbit”的消息將會被丟棄柑爸,因?yàn)樗鼈儧]有匹配任何bindingKey吵护。
headers
headers類型的Exchange不依賴于routing key與binding key的匹配規(guī)則來路由消息,而是根據(jù)發(fā)送的消息內(nèi)容中的headers屬性進(jìn)行匹配表鳍。
在綁定Queue與Exchange時(shí)指定一組鍵值對馅而;當(dāng)消息發(fā)送到Exchange時(shí),RabbitMQ會取到該消息的headers(也是一個(gè)鍵值對的形式)譬圣,對比其中的鍵值對是否完全匹配Queue與Exchange綁定時(shí)指定的鍵值對瓮恭;如果完全匹配則消息會路由到該Queue,否則不會路由到該Queue厘熟。
該類型的Exchange沒有用到過(不過也應(yīng)該很有用武之地)屯蹦,所以不做介紹。
RPC
MQ本身是基于異步的消息處理绳姨,前面的示例中所有的生產(chǎn)者(P)將消息發(fā)送到RabbitMQ后不會知道消費(fèi)者(C)處理成功或者失數抢健(甚至連有沒有消費(fèi)者來處理這條消息都不知道)。
但實(shí)際的應(yīng)用場景中飘庄,我們很可能需要一些同步處理脑蠕,需要同步等待服務(wù)端將我的消息處理完成后再進(jìn)行下一步處理。這相當(dāng)于RPC(Remote Procedure Call跪削,遠(yuǎn)程過程調(diào)用)谴仙。
在RabbitMQ中也支持RPC。
image.png
RabbitMQ中實(shí)現(xiàn)RPC的機(jī)制是:
客戶端發(fā)送請求(消息)時(shí)碾盐,在消息的屬性(MessageProperties晃跺,在AMQP協(xié)議中定義了14中properties,這些屬性會隨著消息一起發(fā)送)中設(shè)置兩個(gè)值replyTo(一個(gè)Queue名稱廓旬,用于告訴服務(wù)器處理完成后將通知我的消息發(fā)送到這個(gè)Queue中)和correlationId(此次請求的標(biāo)識號哼审,服務(wù)器處理完成后需要將此屬性返還谐腰,客戶端將根據(jù)這個(gè)id了解哪條請求被成功執(zhí)行了或執(zhí)行失敗)
服務(wù)器端收到消息并處理
服務(wù)器端處理完消息后涩盾,將生成一條應(yīng)答消息到replyTo指定的Queue十气,同時(shí)帶上correlationId屬性
客戶端之前已訂閱replyTo指定的Queue,從中收到服務(wù)器的應(yīng)答消息后春霍,根據(jù)其中的correlationId屬性分析哪條請求被執(zhí)行了砸西,根據(jù)執(zhí)行結(jié)果進(jìn)行后續(xù)業(yè)務(wù)處理
5. 細(xì)節(jié)闡明
使用ack確認(rèn)Message的正確傳遞
默認(rèn)情況下,如果Message 已經(jīng)被某個(gè)Consumer正確的接收到了址儒,那么該Message就會被從queue中移除芹枷。當(dāng)然也可以讓同一個(gè)Message發(fā)送到很多的Consumer。
如果一個(gè)queue沒被任何的Consumer Subscribe(訂閱)莲趣,那么鸳慈,如果這個(gè)queue有數(shù)據(jù)到達(dá),那么這個(gè)數(shù)據(jù)會被cache喧伞,不會被丟棄走芋。當(dāng)有Consumer時(shí),這個(gè)數(shù)據(jù)會被立即發(fā)送到這個(gè)Consumer潘鲫,這個(gè)數(shù)據(jù)被Consumer正確收到時(shí)翁逞,這個(gè)數(shù)據(jù)就被從queue中刪除。
那么什么是正確收到呢溉仑?通過ack挖函。每個(gè)Message都要被acknowledged(確認(rèn),ack)浊竟。我們可以顯示的在程序中去ack怨喘,也可以自動(dòng)的ack。如果有數(shù)據(jù)沒有被ack逐沙,那么RabbitMQ Server會把這個(gè)信息發(fā)送到下一個(gè)Consumer哲思。
如果這個(gè)app有bug,忘記了ack吩案,那么RabbitMQ Server不會再發(fā)送數(shù)據(jù)給它棚赔,因?yàn)镾erver認(rèn)為這個(gè)Consumer處理能力有限。
而且ack的機(jī)制可以起到限流的作用(Benefitto throttling):在Consumer處理完成數(shù)據(jù)后發(fā)送ack徘郭,甚至在額外的延時(shí)后發(fā)送ack,將有效的balance Consumer的load残揉。
當(dāng)然對于實(shí)際的例子胧后,比如我們可能會對某些數(shù)據(jù)進(jìn)行merge,比如merge 4s內(nèi)的數(shù)據(jù)抱环,然后sleep 4s后再獲取數(shù)據(jù)壳快。特別是在監(jiān)聽系統(tǒng)的state纸巷,我們不希望所有的state實(shí)時(shí)的傳遞上去,而是希望有一定的延時(shí)眶痰。這樣可以減少某些IO瘤旨,而且終端用戶也不會感覺到。
Reject a message
有兩種方式竖伯,第一種的Reject可以讓RabbitMQ Server將該Message 發(fā)送到下一個(gè)Consumer存哲。第二種是從queue中立即刪除該Message。
Creating a queue
Consumer和Procuder都可以通過 queue.declare 創(chuàng)建queue七婴。對于某個(gè)Channel來說祟偷,Consumer不能declare一個(gè)queue,卻訂閱其他的queue打厘。當(dāng)然也可以創(chuàng)建私有的queue修肠。這樣只有app本身才可以使用這個(gè)queue。queue也可以自動(dòng)刪除婚惫,被標(biāo)為auto-delete的queue在最后一個(gè)Consumer unsubscribe后就會被自動(dòng)刪除氛赐。那么如果是創(chuàng)建一個(gè)已經(jīng)存在的queue呢?那么不會有任何的影響先舷。需要注意的是沒有任何的影響,也就是說第二次創(chuàng)建如果參數(shù)和第一次不一樣滓侍,那么該操作雖然成功蒋川,但是queue的屬性并不會被修改。
那么誰應(yīng)該負(fù)責(zé)創(chuàng)建這個(gè)queue呢撩笆?是Consumer捺球,還是Producer?
如果queue不存在夕冲,當(dāng)然Consumer不會得到任何的Message氮兵。但是如果queue不存在,那么Producer Publish的Message會被丟棄歹鱼。所以泣栈,還是為了數(shù)據(jù)不丟失,Consumer和Producer都try to create the queue弥姻!反正不管怎么樣南片,這個(gè)接口都不會出問題。
queue對load balance的處理是完美的庭敦。對于多個(gè)Consumer來說疼进,RabbitMQ 使用循環(huán)的方式(round-robin)的方式均衡的發(fā)送給不同的Consumer。
Exchanges
從架構(gòu)圖可以看出秧廉,Procuder Publish的Message進(jìn)入了Exchange伞广。接著通過“routing keys”拣帽, RabbitMQ會找到應(yīng)該把這個(gè)Message放到哪個(gè)queue里。queue也是通過這個(gè)routing keys來做的綁定嚼锄。
有三種類型的Exchanges:direct, fanout,topic诞外。 每個(gè)實(shí)現(xiàn)了不同的路由算法(routing algorithm)。
Direct exchange: 如果 routing key 匹配, 那么Message就會被傳遞到相應(yīng)的queue中灾票。其實(shí)在queue創(chuàng)建時(shí)峡谊,它會自動(dòng)的以queue的名字作為routing key來綁定那個(gè)exchange。
Fanout exchange: 會向響應(yīng)的queue廣播刊苍。
Topic exchange:對key進(jìn)行模式匹配既们,比如ab可以傳遞到所有ab的queue。
Virtual hosts
每個(gè)virtual host本質(zhì)上都是一個(gè)RabbitMQ Server正什,擁有它自己的queue啥纸,exchagne,和bings rule等等婴氮。這保證了你可以在多個(gè)不同的application中使用RabbitMQ斯棒。
作者:高廣超
鏈接:http://www.reibang.com/p/24f464f9161c
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)主经,非商業(yè)轉(zhuǎn)載請注明出處荣暮。