感興趣的同學(xué)可以灌水哦,網(wǎng)址:http://www.wangkun.xyz/
歡迎來找bug和提(gao)需(shi)求(qing)
支持QQ和微博快捷登錄,免注冊(cè),想要相關(guān)源碼請(qǐng)發(fā)布問答留言
消息隊(duì)列中間件簡(jiǎn)介
? 消息隊(duì)列中間件是分布式系統(tǒng)中重要的組件,主要解決應(yīng)用耦合,異步消息,流量 削鋒等問題實(shí)現(xiàn)高性能,高可用,可伸縮和終一致性[架構(gòu)] 使用較多的消息隊(duì)列有 ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ
什么是RabbitMQ
RabbitMQ 是一個(gè)由 Erlang 語言開發(fā)的 AMQP 的開源實(shí)現(xiàn)。
RabbitMQ 初起源于金融系統(tǒng),用于在分布式系統(tǒng)中存儲(chǔ)轉(zhuǎn)發(fā)消息,在易用性、擴(kuò)展 性、高可用性等方面表現(xiàn)不俗。具體特點(diǎn)包括:
1.可靠性(Reliability)
RabbitMQ 使用一些機(jī)制來保證可靠性,如持久化、傳輸確認(rèn)、發(fā)布確認(rèn)。
2.靈活的路由(Flexible Routing)
北京市昌平區(qū)建材城西路金燕龍辦公樓一層 電話:400-618-9090
在消息進(jìn)入隊(duì)列之前,通過 Exchange 來路由消息的。對(duì)于典型的路由功能,RabbitMQ 已經(jīng)提供了一些內(nèi)置的 Exchange 來實(shí)現(xiàn)。針對(duì)更復(fù)雜的路由功能,可以將多個(gè) Exchange 綁定在一起,也通過插件機(jī)制實(shí)現(xiàn)自己的 Exchange 。
3.消息集群(Clustering)
多個(gè) RabbitMQ 服務(wù)器可以組成一個(gè)集群,形成一個(gè)邏輯 Broker 。 4.高可用(Highly Available Queues)
隊(duì)列可以在集群中的機(jī)器上進(jìn)行鏡像,使得在部分節(jié)點(diǎn)出問題的情況下隊(duì)列仍然可用。
5.多種協(xié)議(Multi-protocol)
RabbitMQ 支持多種消息隊(duì)列協(xié)議,比如 STOMP、MQTT 等等。
6.多語言客戶端(Many Clients) RabbitMQ 幾乎支持所有常用語言,比如 Java、.NET、Ruby 等等。
7.管理界面(Management UI)
RabbitMQ 提供了一個(gè)易用的用戶界面,使得用戶可以監(jiān)控和管理消息 Broker 的許多方 面。
8.跟蹤機(jī)制(Tracing)
如果消息異常,RabbitMQ 提供了消息跟蹤機(jī)制,使用者可以找出發(fā)生了什么。 9.插件機(jī)制(Plugin System)
RabbitMQ 提供了許多插件,來從多方面進(jìn)行擴(kuò)展,也可以編寫自己的插件。
## 主要概念 ##
RabbitMQ Server: 也叫broker server,它是一種傳輸服務(wù)。 他的角色就是維護(hù)一條 從Producer到Consumer的路線,保證數(shù)據(jù)能夠按照指定的方式進(jìn)行傳輸。
Producer:
消息生產(chǎn)者,如圖A、B、C,數(shù)據(jù)的發(fā)送方。消息生產(chǎn)者連接RabbitMQ服 務(wù)器然后將消息投遞到Exchange。
#Consumer:消息消費(fèi)者,如圖1、2、3,數(shù)據(jù)的接收方。消息消費(fèi)者訂閱隊(duì)列, RabbitMQ將Queue中的消息發(fā)送到消息消費(fèi)者。
Exchange:生產(chǎn)者將消息發(fā)送到Exchange(交換器),由Exchange將消息路由到一個(gè) 或多個(gè)Queue中(或者丟棄)。Exchange并不存儲(chǔ)消息。RabbitMQ中的Exchange有 direct、fanout、topic、headers四種類型,每種類型對(duì)應(yīng)不同的路由規(guī)則。
#Queue:
(隊(duì)列)是RabbitMQ的內(nèi)部對(duì)象,用于存儲(chǔ)消息。消息消費(fèi)者就是通過訂閱 隊(duì)列來獲取消息的,RabbitMQ中的消息都只能存儲(chǔ)在Queue中,生產(chǎn)者生產(chǎn)消息并終 投遞到Queue中,消費(fèi)者可以從Queue中獲取消息并消費(fèi)。多個(gè)消費(fèi)者可以訂閱同一個(gè) Queue,這時(shí)Queue中的消息會(huì)被平均分?jǐn)偨o多個(gè)消費(fèi)者進(jìn)行處理,而不是每個(gè)消費(fèi)者 都收到所有的消息并處理。
#RoutingKey:
生產(chǎn)者在將消息發(fā)送給Exchange的時(shí)候,一般會(huì)指定一個(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è)定的長(zhǎng)度限制為255 bytes。
#Connection: (連接):
Producer和Consumer都是通過TCP連接到RabbitMQ Server 的。以后我們可以看到,程序的起始處就是建立這個(gè)TCP連接。
Channels: (信道):
它建立在上述的TCP連接中。數(shù)據(jù)流動(dòng)都是在Channel中進(jìn)行 的。也就是說,一般情況是程序起始建立TCP連接,第二步就是建立這個(gè)Channel。
VirtualHost:
權(quán)限控制的基本單位,一個(gè)VirtualHost里面有若干Exchange和 MessageQueue,以及指定被哪些user使用
1、什么是RabbitMQ?為什么使用RabbitMQ?
答:RabbitMQ是一款開源的,Erlang編寫的,基于AMQP協(xié)議的,消息中間件;
可以用它來:解耦、異步、削峰。
2、RabbitMQ有什么優(yōu)缺點(diǎn)?
答:優(yōu)點(diǎn):解耦、異步、削峰;
缺點(diǎn):降低了系統(tǒng)的穩(wěn)定性:本來系統(tǒng)運(yùn)行好好的,現(xiàn)在你非要加入個(gè)消息隊(duì)列進(jìn)去,那消息隊(duì)列掛了,你的系統(tǒng)不是呵呵了。因此,系統(tǒng)可用性會(huì)降低;
增加了系統(tǒng)的復(fù)雜性:加入了消息隊(duì)列,要多考慮很多方面的問題,比如:一致性問題、如何保證消息不被重復(fù)消費(fèi)、如何保證消息可靠性傳輸?shù)?。因此,需要考慮的東西更多,復(fù)雜性增大。
3、如何保證RabbitMQ的高可用?
答:沒有哪個(gè)項(xiàng)目會(huì)只用一搭建一臺(tái)RabbitMQ服務(wù)器提供服務(wù),風(fēng)險(xiǎn)太大;
4、如何保證RabbitMQ不被重復(fù)消費(fèi)?
答:先說為什么會(huì)重復(fù)消費(fèi):正常情況下,消費(fèi)者在消費(fèi)消息的時(shí)候,消費(fèi)完畢后,會(huì)發(fā)送一個(gè)確認(rèn)消息給消息隊(duì)列,消息隊(duì)列就知道該消息被消費(fèi)了,就會(huì)將該消息從消息隊(duì)列中刪除;
但是因?yàn)榫W(wǎng)絡(luò)傳輸?shù)鹊裙收希_認(rèn)信息沒有傳送到消息隊(duì)列,導(dǎo)致消息隊(duì)列不知道自己已經(jīng)消費(fèi)過該消息了,再次將消息分發(fā)給其他的消費(fèi)者。
針對(duì)以上問題,一個(gè)解決思路是:保證消息的唯一性,就算是多次傳輸,不要讓消息的多次消費(fèi)帶來影響;保證消息等冪性;
比如:在寫入消息隊(duì)列的數(shù)據(jù)做唯一標(biāo)示,消費(fèi)消息時(shí),根據(jù)唯一標(biāo)識(shí)判斷是否消費(fèi)過;
5、如何保證RabbitMQ消息的可靠傳輸?
答:消息不可靠的情況可能是消息丟失,劫持等原因;
丟失又分為:生產(chǎn)者丟失消息、消息列表丟失消息、消費(fèi)者丟失消息;
生產(chǎn)者丟失消息:從生產(chǎn)者弄丟數(shù)據(jù)這個(gè)角度來看,RabbitMQ提供transaction和confirm模式來確保生產(chǎn)者不丟消息;
transaction機(jī)制就是說:發(fā)送消息前,開啟事務(wù)(channel.txSelect()),然后發(fā)送消息,如果發(fā)送過程中出現(xiàn)什么異常,事務(wù)就會(huì)回滾(channel.txRollback()),如果發(fā)送成功則提交事務(wù)(channel.txCommit())。然而,這種方式有個(gè)缺點(diǎn):吞吐量下降;
confirm模式用的居多:一旦channel進(jìn)入confirm模式,所有在該信道上發(fā)布的消息都將會(huì)被指派一個(gè)唯一的ID(從1開始),一旦消息被投遞到所有匹配的隊(duì)列之后;
rabbitMQ就會(huì)發(fā)送一個(gè)ACK給生產(chǎn)者(包含消息的唯一ID),這就使得生產(chǎn)者知道消息已經(jīng)正確到達(dá)目的隊(duì)列了;
如果rabbitMQ沒能處理該消息,則會(huì)發(fā)送一個(gè)Nack消息給你,你可以進(jìn)行重試操作。
消息隊(duì)列丟數(shù)據(jù):消息持久化。
處理消息隊(duì)列丟數(shù)據(jù)的情況,一般是開啟持久化磁盤的配置。
這個(gè)持久化配置可以和confirm機(jī)制配合使用,你可以在消息持久化磁盤后,再給生產(chǎn)者發(fā)送一個(gè)Ack信號(hào)。
這樣,如果消息持久化磁盤之前,rabbitMQ陣亡了,那么生產(chǎn)者收不到Ack信號(hào),生產(chǎn)者會(huì)自動(dòng)重發(fā)。
那么如何持久化呢?
這里順便說一下吧,其實(shí)也很容易,就下面兩步
將queue的持久化標(biāo)識(shí)durable設(shè)置為true,則代表是一個(gè)持久的隊(duì)列
發(fā)送消息的時(shí)候?qū)eliveryMode=2
這樣設(shè)置以后,即使rabbitMQ掛了,重啟后也能恢復(fù)數(shù)據(jù)
消費(fèi)者丟失消息:消費(fèi)者丟數(shù)據(jù)一般是因?yàn)椴捎昧俗詣?dòng)確認(rèn)消息模式,改為手動(dòng)確認(rèn)消息即可!
消費(fèi)者在收到消息之后,處理消息之前,會(huì)自動(dòng)回復(fù)RabbitMQ已收到消息;
如果這時(shí)處理消息失敗,就會(huì)丟失該消息;
解決方案:處理消息成功后,手動(dòng)回復(fù)確認(rèn)消息。
6、如何保證RabbitMQ消息的順序性?
答:?jiǎn)尉€程消費(fèi)保證消息的順序性;對(duì)消息進(jìn)行編號(hào),消費(fèi)者處理消息是根據(jù)編號(hào)處理消息;
問題一:RabbitMQ 中的 broker 是指什么?cluster 又是指什么?
答:broker 是指一個(gè)或多個(gè) erlang node 的邏輯分組,且 node 上運(yùn)行著 RabbitMQ 應(yīng)用
程序。cluster 是在 broker 的基礎(chǔ)之上,增加了 node 之間共享元數(shù)據(jù)的約束。
問題二:什么是元數(shù)據(jù)?元數(shù)據(jù)分為哪些類型?包括哪些內(nèi)容?與 cluster 相關(guān)的元數(shù)據(jù)
有哪些?元數(shù)據(jù)是如何保存的?元數(shù)據(jù)在 cluster 中是如何分布的?
答:在非 cluster 模式下,元數(shù)據(jù)主要分為 Queue 元數(shù)據(jù)(queue 名字和屬性等)、
Exchange 元數(shù)據(jù)(exchange 名字、類型和屬性等)、Binding 元數(shù)據(jù)(存放路由關(guān)系的查
找表)、Vhost 元數(shù)據(jù)(vhost 范圍內(nèi)針對(duì)前三者的名字空間約束和安全屬性設(shè)置)。在
cluster 模式下,還包括 cluster 中 node 位置信息和 node 關(guān)系信息。元數(shù)據(jù)按照 erlang
node 的類型確定是僅保存于 RAM 中,還是同時(shí)保存在 RAM 和 disk 上。元數(shù)據(jù)在
cluster 中是全 node 分布的。
問題三:RAM node 和 disk node 的區(qū)別?
答:RAM node 僅將 fabric(即 queue、exchange 和 binding 等 RabbitMQ 基礎(chǔ)構(gòu)件)相
關(guān)元數(shù)據(jù)保存到內(nèi)存中,但 disk node 會(huì)在內(nèi)存和磁盤中均進(jìn)行存儲(chǔ)。RAM node 上唯一
會(huì)存儲(chǔ)到磁盤上的元數(shù)據(jù)是 cluster 中使用的 disk node 的地址。要求在 RabbitMQ cluster
中至少存在一個(gè) disk node 。
問題四:RabbitMQ 上的一個(gè) queue 中存放的 message 是否有數(shù)量限制?
答:可以認(rèn)為是無限制,因?yàn)橄拗迫Q于機(jī)器的內(nèi)存,但是消息過多會(huì)導(dǎo)致處理效率的下
降。
問題五:RabbitMQ 概念里的 channel、exchange 和 queue 這些東東是邏輯概念,還是對(duì)應(yīng)著進(jìn)程實(shí)體?這些東東分別起什么作用?
答:queue 具有自己的 erlang 進(jìn)程;exchange 內(nèi)部實(shí)現(xiàn)為保存 binding 關(guān)系的查找表;
channel 是實(shí)際進(jìn)行路由工作的實(shí)體,即負(fù)責(zé)按照 routing_key 將 message 投遞給
queue 。由 AMQP 協(xié)議描述可知,channel 是真實(shí) TCP 連接之上的虛擬連接,所有
AMQP 命令都是通過 channel 發(fā)送的,且每一個(gè) channel 有唯一的 ID。一個(gè) channel 只
能被單獨(dú)一個(gè)操作系統(tǒng)線程使用,故投遞到特定 channel 上的 message 是有順序的。但
一個(gè)操作系統(tǒng)線程上允許使用多個(gè) channel 。channel 號(hào)為 0 的 channel 用于處理所有
對(duì)于當(dāng)前 connection 全局有效的幀,而 1-65535 號(hào) channel 用于處理和特定 channel 相
關(guān)的幀。AMQP 協(xié)議給出的 channel 復(fù)用模型如下
其中每一個(gè) channel 運(yùn)行在一個(gè)獨(dú)立的線程上,多線程共享同一個(gè) socket。
問題六:vhost 是什么?起什么作用?
答:vhost 可以理解為虛擬 broker ,即 mini-RabbitMQ server。其內(nèi)部均含有獨(dú)立的
queue、exchange 和 binding 等,但最最重要的是,其擁有獨(dú)立的權(quán)限系統(tǒng),可以做到
vhost 范圍的用戶控制。當(dāng)然,從 RabbitMQ 的全局角度,vhost 可以作為不同權(quán)限隔離
的手段(一個(gè)典型的例子就是不同的應(yīng)用可以跑在不同的 vhost 中)。