你們好,我是Java最全面試題庫
的提褲姐,今天這篇是中間件面試題系列的第一篇,主要總結了RabbitMQ相關的面試題;在後續,會沿着第一篇開篇的知識線路一直總結下去,作到日更!若是我能作到百日百更,但願你也能夠跟着百日百刷,一百天養成一個好習慣。面試
RabbitMQ是一款開源的,Erlang編寫的,基於AMQP協議的,消息中間件;
能夠用它來:解耦
、異步
、削峯
。服務器
加入了消息隊列,要多考慮不少方面的問題,好比:一致性問題、如何保證消息不被重複消費、如何保證消息可靠性傳輸等。所以,須要考慮的東西更多,複雜性增大。網絡
Broker
: 消息隊列服務器實體Exchange
: 消息交換機,它指定消息按特定規則,路由到哪一個隊列Queue
: 消息隊列載體,每一個消息都會被投入到一個或多個隊列Binding
: 綁定,它的做用就是把exchange和queue按照路由規則綁定起來Routing Key
: 路由關鍵字,exchange根據這個關鍵字進行消息投遞VHost
: vhost 能夠理解爲虛擬 broker ,即 mini-RabbitMQ server。其內部均含有獨立的 queue、exchange 和 binding 等,擁有獨立的權限系統,能夠作到 vhost 範圍的用戶控制。Producer
: 消息生產者Consumer
: 消息消費者Channel
: 消息通道,在客戶端的每一個鏈接裏,可創建多個channel,每一個channel表明一個會話任務正常狀況下,消費者在消費消息的時候,消費完畢後,會發送一個確認消息給消息隊列,消息隊列就知道該消息被消費了,就會將該消息從消息隊列中刪除;異步
可是由於網絡傳輸等等故障,確認信息沒有傳送到消息隊列,致使消息隊列不知道本身已經消費過該消息了,再次將消息分發給其餘的消費者。操作系統
解決思路:
保證消息的惟一性,就算是屢次傳輸,不要讓消息的屢次消費帶來影響;保證消息等冪性;
好比:在寫入消息隊列的數據作惟一標識,消費消息時,根據惟一標識判斷是否消費過;線程
queue 具備本身的 erlang
進程;
exchange 內部實現爲保存 binding
關係的查找表;
channel 是實際進行路由工做的實體,即負責按照 routing_key 將 message 投遞給 queue 。code
由 AMQP 協議描述可知,channel
是真實 TCP 鏈接之上的虛擬鏈接
,全部 AMQP 命令都是經過 channel 發送的,且每個 channel 有惟一的 ID
。一個 channel 只能被單獨一個操做系統線程使用,故投遞到特定 channel 上的 message 是有順序的。但一個操做系統線程上容許使用多個 channel 。server
從概念上來講,消息路由必須有三部分:交換器、路由、綁定。中間件
生產者把消息發佈到交換器上;綁定決定了消息如何從路由器路由到特定的隊列;消息最終到達隊列,並被消費者接收。
消息發佈到交換器時,消息將擁有一個路由鍵(routing key)
,在消息建立時設定。
經過隊列路由鍵,能夠把隊列綁定到交換器上。
消息到達交換器後,RabbitMQ會將消息的路由鍵與隊列的路由鍵進行匹配(針對不一樣的交換器有不一樣的路由規則)。若是可以匹配到隊列,則消息會投遞到相應隊列中;若是不能匹配到任何隊列,消息將進入 「黑洞」。rabbitmq
經常使用的交換器主要分爲一下三種:
direct
:若是路由鍵徹底匹配,消息就被投遞到相應的隊列fanout
:若是交換器收到消息,將會廣播到全部綁定的隊列上topic
:可使來自不一樣源頭的消息可以到達同一個隊列。 使用topic交換器時,可使用通配符,好比:「*」
匹配特定位置的任意文本, 「.」
把路由鍵分爲了幾部分,「#」
匹配全部規則等。特別注意:發往topic交換器的消息不能隨意的設置選擇鍵(routing_key),必須是由"."隔開的一系列的標識符組成。
消息不可靠的狀況多是消息丟失,劫持等緣由
丟失又分爲:
生產者丟失消息:
從生產者弄丟數據這個角度來看,RabbitMQ提供transaction機制
和confirm模式
來確保生產者不丟消息;
若是RabbitMQ沒能處理該消息,則會發送一個Nack消息給你,你能夠進行重試操做。
消息隊列丟數據:
消息持久化,處理消息隊列丟數據的狀況,通常是開啓持久化磁盤的配置:
將隊列的持久化標識durable
設置爲true
,則表明是一個持久的隊列 發送消息的時候將 deliveryMode=2
這樣設置之後,即便RabbitMQ掛了,重啓後也能恢復數據
消費者丟失消息:
消費者丟數據通常是由於採用了自動確認消息模式,改成手動確認消息
消費者在收到消息以後,處理消息以前,會自動回覆RabbitMQ已收到消息; 若是這時處理消息失敗,就會丟失該消息;
解決方案:處理消息成功後,手動回覆確認消息。
一、單線程
消費保證消息的順序性;
二、對消息進行編號
,消費者處理消息是根據編號處理消息;
死信隊列:
死信,顧名思義就是沒法被消費的消息,字面意思能夠這樣理解,通常來講,producer將消息投遞到broker或者直接到queue裏了,consumer從queue取出消息進行消費,但某些時候因爲特定的緣由致使queue中的某些消息沒法被消費,這樣的消息若是沒有後續的處理,就變成了死信,有死信,天然就有了死信隊列;
死信消息:
一、消息被拒絕(Basic.Reject
或Basic.Nack
)而且設置 requeue 參數的值爲 false
二、消息過時了
三、隊列達到最大的長度
過時消息:
在 rabbitmq 中存在2種方可設置消息的過時時間,
若是同時使用這2種方法,那麼以過時時間小的那個數值爲準。當消息達到過時時間尚未被消費,那麼那個消息就成爲了一個 死信 消息。
隊列設置:在隊列申明的時候使用 x-message-ttl
參數,單位爲 毫秒
單個消息設置:是設置消息屬性的 expiration
參數的值,單位爲 毫秒
延時隊列:在rabbitmq中不存在延時隊列,可是咱們能夠經過設置消息的過時時間和死信隊列來模擬出延時隊列。消費者監聽死信交換器綁定的隊列,而不要監聽消息發送的隊列。