二十四個RabbitMQ消息中間件面試題及答案(雙手奉上,拿走不行)

二十四個RabbitMQ消息中間件面試題及答案(雙手奉上,拿走不行)

 

問題一:RabbitMQ 中的 broker 是指什麼?cluster 又是指什麼?node

答:broker 是指一個或多個 erlang node 的邏輯分組,且 node 上運行着 RabbitMQ 應用面試

程序。cluster 是在 broker 的基礎之上,增長了 node 之間共享元數據的約束。安全

問題二:什麼是元數據?元數據分爲哪些類型?包括哪些內容?與 cluster 相關的元數據服務器

有哪些?元數據是如何保存的?元數據在 cluster 中是如何分佈的?多線程

答:在非 cluster 模式下,元數據主要分爲 Queue 元數據(queue 名字和屬性等)、負載均衡

Exchange 元數據(exchange 名字、類型和屬性等)、Binding 元數據(存放路由關係的查框架

找表)、Vhost 元數據(vhost 範圍內針對前三者的名字空間約束和安全屬性設置)。在socket

cluster 模式下,還包括 cluster 中 node 位置信息和 node 關係信息。元數據按照 erlang性能

node 的類型肯定是僅保存於 RAM 中,仍是同時保存在 RAM 和 disk 上。元數據在操作系統

cluster 中是全 node 分佈的。

問題三:RAM node 和 disk node 的區別?

答:RAM node 僅將 fabric(即 queue、exchange 和 binding 等 RabbitMQ 基礎構件)相

關元數據保存到內存中,但 disk node 會在內存和磁盤中均進行存儲。RAM node 上惟一

會存儲到磁盤上的元數據是 cluster 中使用的 disk node 的地址。要求在 RabbitMQ cluster

中至少存在一個 disk node 。

問題四:RabbitMQ 上的一個 queue 中存放的 message 是否有數量限制?

答:能夠認爲是無限制,由於限制取決於機器的內存,可是消息過多會致使處理效率的下

降。

問題五:RabbitMQ 概念裏的 channel、exchange 和 queue 這些東東是邏輯概念,仍是對應着進程實體?這些東東分別起什麼做用?

答:queue 具備本身的 erlang 進程;exchange 內部實現爲保存 binding 關係的查找表;

channel 是實際進行路由工做的實體,即負責按照 routing_key 將 message 投遞給

queue 。由 AMQP 協議描述可知,channel 是真實 TCP 鏈接之上的虛擬鏈接,全部

AMQP 命令都是經過 channel 發送的,且每個 channel 有惟一的 ID。一個 channel 只

能被單獨一個操做系統線程使用,故投遞到特定 channel 上的 message 是有順序的。但

一個操做系統線程上容許使用多個 channel 。channel 號爲 0 的 channel 用於處理全部

對於當前 connection 全局有效的幀,而 1-65535 號 channel 用於處理和特定 channel 相

關的幀。AMQP 協議給出的 channel 複用模型以下

其中每個 channel 運行在一個獨立的線程上,多線程共享同一個 socket。

問題六:vhost 是什麼?起什麼做用?

答:vhost 能夠理解爲虛擬 broker ,即 mini-RabbitMQ server。其內部均含有獨立的

queue、exchange 和 binding 等,但最最重要的是,其擁有獨立的權限系統,能夠作到

vhost 範圍的用戶控制。固然,從 RabbitMQ 的全局角度,vhost 能夠做爲不一樣權限隔離

的手段(一個典型的例子就是不一樣的應用能夠跑在不一樣的 vhost 中)。

【cluster 相關】

問題七:在單 node 系統和多 node 構成的 cluster 系統中聲明 queue、exchange ,以及

進行 binding 會有什麼不一樣?

答:當你在單 node 上聲明 queue 時,只要該 node 上相關元數據進行了變動,你就會

獲得 Queue.Declare-ok 迴應;而在 cluster 上聲明 queue ,則要求 cluster 上的所有

node 都要進行元數據成功更新,纔會獲得 Queue.Declare-ok 迴應。另外,若 node 類型

爲 RAM node 則變動的數據僅保存在內存中,若類型爲 disk node 則還要變動保存在磁盤

上的數據。

問題八:客戶端鏈接到 cluster 中的任意 node 上是否都能正常工做?

答:是的。客戶端感受不到有何不一樣。

問題九:若 cluster 中擁有某個 queue 的 owner node 失效了,且該 queue 被聲明具備

durable 屬性,是否可以成功從其餘 node 上從新聲明該 queue ?

答:不能,在這種狀況下,將獲得 404 NOT_FOUND 錯誤。只能等 queue 所屬的 node

恢復後才能使用該 queue 。但若該 queue 自己不具備 durable 屬性,則可在其餘 node

上從新聲明。

問題十:cluster 中 node 的失效會對 consumer 產生什麼影響?如果在 cluster 中建立了

mirrored queue ,這時 node 失效會對 consumer 產生什麼影響?

答:如果 consumer 所鏈接的那個 node 失效(不管該 node 是否爲 consumer 所訂閱

queue 的 owner node),則 consumer 會在發現 TCP 鏈接斷開時,按標準行爲執行重連

邏輯,並根據「Assume Nothing」原則重建相應的 fabric 便可。如果失效的 node 爲

consumer 訂閱 queue 的 owner node,則 consumer 只能經過 Consumer Cancellation

Notification 機制來檢測與該 queue 訂閱關係的終止,不然會出現傻等卻沒有任何消息來

到的問題。

問題十一:可以在地理上分開的不一樣數據中心使用 RabbitMQ cluster 麼?

答:不能。第一,你沒法控制所建立的 queue 實際分佈在 cluster 裏的哪一個 node 上(一

般使用 HAProxy + cluster 模型時都是這樣),這可能會致使各類跨地域訪問時的常見問

題;第二,Erlang 的 OTP 通訊框架對延遲的容忍度有限,這可能會觸發各類超時,致使

業務疲於處理;第三,在廣域網上的鏈接失效問題將致使經典的「腦裂」問題,而

RabbitMQ 目前沒法處理(該問題主要是說 Mnesia)。

【綜合問題】

問題十二:爲何 heavy RPC 的使用場景下不建議採用 disk node ?

答:heavy RPC 是指在業務邏輯中高頻調用 RabbitMQ 提供的 RPC 機制,致使不斷建立、

銷燬 reply queue ,進而形成 disk node 的性能問題(由於會針對元數據不斷寫盤)。因此

在使用 RPC 機制時須要考慮自身的業務場景。

問題十三:向不存在的 exchange 發 publish 消息會發生什麼?向不存在的 queue 執行

consume 動做會發生什麼?

答:都會收到 Channel.Close 信令告之不存在(內含緣由 404 NOT_FOUND)。

問題十四:routing_key 和 binding_key 的最大長度是多少?

答:255 字節。

問題十五:RabbitMQ 容許發送的 message 最大可達多大?

答:根據 AMQP 協議規定,消息體的大小由 64-bit 的值來指定,因此你就能夠知道到底

能發多大的數據了。

問題十六:什麼狀況下 producer 不主動建立 queue 是安全的?

答:1.message 是容許丟失的;2.實現了針對未處理消息的 republish 功能(例如採用

Publisher Confirm 機制)。

問題十七:「dead letter」queue 的用途?

答:當消息被 RabbitMQ server 投遞到 consumer 後,但 consumer 卻經過 Basic.Reject

進行了拒絕時(同時設置 requeue=false),那麼該消息會被放入「dead letter」queue 中。

該 queue 可用於排查 message 被 reject 或 undeliver 的緣由。

問題十八:爲何說保證 message 被可靠持久化的條件是 queue 和 exchange 具備

durable 屬性,同時 message 具備 persistent 屬性才行?

答:binding 關係能夠表示爲 exchange – binding – queue 。從文檔中咱們知道,若要求

投遞的 message 可以不丟失,要求 message 自己設置 persistent 屬性,要求 exchange

和 queue 都設置 durable 屬性。其實這問題能夠這麼想,若 exchange 或 queue 未設置

durable 屬性,則在其 crash 以後就會沒法恢復,那麼即便 message 設置了 persistent 屬

性,仍然存在 message 雖然能恢復但卻無處容身的問題;同理,若 message 自己未設置

persistent 屬性,則 message 的持久化更無從談起。

問題十九:什麼狀況下會出現 blackholed 問題?

答:blackholed 問題是指,向 exchange 投遞了 message ,而因爲各類緣由致使該

message 丟失,但發送者殊不知道。可致使 blackholed 的狀況:1.向未綁定 queue 的

exchange 發送 message;2.exchange 以 binding_key key_A 綁定了 queue queue_A,但向

該 exchange 發送 message 使用的 routing_key 倒是 key_B。

問題二十:如何防止出現 blackholed 問題?

答:沒有特別好的辦法,只能在具體實踐中經過各類方式保證相關 fabric 的存在。另外,

若是在執行 Basic.Publish 時設置 mandatory=true ,則在遇到可能出現 blackholed 狀況

時,服務器會經過返回 Basic.Return 告之當前 message 沒法被正確投遞(內含緣由 312

NO_ROUTE)。

問題二十一:Consumer Cancellation Notification 機制用於什麼場景?

答:用於保證當鏡像 queue 中 master 掛掉時,鏈接到 slave 上的 consumer 能夠收到自

身 consume 被取消的通知,進而能夠從新執行 consume 動做重新選出的 master 出得到

消息。若不採用該機制,鏈接到 slave 上的 consumer 將不會感知 master 掛掉這個事

情,致使後續沒法再收到新 master 廣播出來的 message 。另外,由於在鏡像 queue 模

式下,存在將 message 進行 requeue 的可能,因此實現 consumer 的邏輯時須要可以正

確處理出現重複 message 的狀況。

問題二十二:Basic.Reject 的用法是什麼?

答:該信令可用於 consumer 對收到的 message 進行 reject 。若在該信令中設置

requeue=true,則當 RabbitMQ server 收到該拒絕信令後,會將該 message 從新發送到下

一個處於 consume 狀態的 consumer 處(理論上仍可能將該消息發送給當前

consumer)。若設置 requeue=false ,則 RabbitMQ server 在收到拒絕信令後,將直接將該

message 從 queue 中移除。

另一種移除 queue 中 message 的小技巧是,consumer 回覆 Basic.Ack 但不對獲取到的

message 作任何處理。

而 Basic.Nack 是對 Basic.Reject 的擴展,以支持一次拒絕多條 message 的能力。

問題二十三:爲何不該該對全部的 message 都使用持久化機制?

答:首先,必然致使性能的降低,由於寫磁盤比寫 RAM 慢的多,message 的吞吐量可能

有 10 倍的差距。其次,message 的持久化機制用在 RabbitMQ 的內置 cluster 方案時會

出現「坑爹」問題。矛盾點在於,若 message 設置了 persistent 屬性,但 queue 未設置

durable 屬性,那麼當該 queue 的 owner node 出現異常後,在未重建該 queue 前,發

往該 queue 的 message 將被 blackholed ;若 message 設置了 persistent 屬性,同時

queue 也設置了 durable 屬性,那麼當 queue 的 owner node 異常且沒法重啓的狀況

下,則該 queue 沒法在其餘 node 上重建,只能等待其 owner node 重啓後,才能恢復

該 queue 的使用,而在這段時間內發送給該 queue 的 message 將被 blackholed 。所

以,是否要對 message 進行持久化,須要綜合考慮性能須要,以及可能遇到的問題。若想

達到 100,000 條/秒以上的消息吞吐量(單 RabbitMQ 服務器),則要麼使用其餘的方式來

確保 message 的可靠 delivery ,要麼使用很是快速的存儲系統以支持全持久化(例如使

用 SSD)。另一種處理原則是:僅對關鍵消息做持久化處理(根據業務重要程度),且應

該保證關鍵消息的量不會致使性能瓶頸。

問題二十四:RabbitMQ 中的 cluster、mirrored queue,以及 warrens 機制分別用於解決什麼問題?存在哪些問題?

答:cluster 是爲了解決當 cluster 中的任意 node 失效後,producer 和 consumer 都可以

經過其餘 node 繼續工做,即提升了可用性;另外能夠經過增長 node 數量增長 cluster

的消息吞吐量的目的。cluster 自己不負責 message 的可靠性問題(該問題由 producer 通

過各類機制自行解決);cluster 沒法解決跨數據中心的問題(即腦裂問題)。另外,在

cluster 前使用 HAProxy 能夠解決 node 的選擇問題,即業務無需知道 cluster 中多個

node 的 ip 地址。能夠利用 HAProxy 進行失效 node 的探測,能夠做負載均衡。下圖爲

HAProxy + cluster 的模型。

Mirrored queue 是爲了解決使用 cluster 時所建立的 queue 的完整信息僅存在於單一

node 上的問題,從另外一個角度增長可用性。若想正確使用該功能,須要保證:1.consumer

須要支持 Consumer Cancellation Notification 機制;2.consumer 必須可以正確處理重複

message 。

Warrens 是爲了解決 cluster 中 message 可能被 blackholed 的問題,即不能接受

producer 不停 republish message 但 RabbitMQ server 無迴應的狀況。Warrens 有兩種構

成方式,一種模型是兩臺獨立的 RabbitMQ server + HAProxy ,其中兩個 server 的狀態分

別爲 active 和 hot-standby 。該模型的特色爲:兩臺 server 之間無任何數據共享和協議

交互,兩臺 server 能夠基於不一樣的 RabbitMQ 版本。以下圖所示

另外一種模型爲兩臺共享存儲的 RabbitMQ server + keepalived ,其中兩個 server 的狀態分

別爲 active 和 cold-standby 。該模型的特色爲:兩臺 server 基於共享存儲能夠作到徹底

恢復,要求必須基於徹底相同的 RabbitMQ 版本。以下圖所示

Warrens 模型存在的問題:對於第一種模型,雖然理論上講不會丟失消息,但若在該模型

上使用持久化機制,就會出現這樣一種狀況,即若做爲 active 的 server 異常後,持久化

在該 server 上的消息將暫時沒法被 consume ,由於此時該 queue 將沒法在做爲 hot-

standby 的 server 上被重建,因此,只能等到異常的 active server 恢復後,才能從其上的

queue 中獲取相應的 message 進行處理。而對於業務來講,須要具備:a.感知 AMQP 連

接斷開後重建各類 fabric 的能力;b.感知 active server 恢復的能力;c.切換回 active

server 的時機控制,以及切回後,針對 message 前後順序產生的變化進行處理的能力。

對於第二種模型,由於是基於共享存儲的模式,因此致使 active server 異常的條件,可能

一樣會致使 cold-standby server 異常;另外,在該模型下,要求 active 和 cold-standby

的 server 必須具備相同的 node 名和 UID ,不然將產生訪問權限問題;最後,因爲該模

型是冷備方案,故沒法保證 cold-standby server 能在你要求的時限內成功啓動。

相關文章
相關標籤/搜索