現在主流的訊息佇列產品都提供了非常完善的訊息可靠性保證機制,可以做到在訊息傳遞的程序中,即使發生網路中斷或者硬體故障,也能確保訊息的可靠傳遞、不丟訊息,
絕大部分丟訊息的原因都是由于開發者不熟悉訊息佇列,沒有正確使用和配置訊息佇列導致的,
檢測訊息丟失的方法
用訊息佇列最尷尬的情況不是丟訊息,而是丟了訊息還不知道,因此,我們需要設計一套機制來監控訊息是否有丟失,
根據專案的成熟程度,一般有兩種方式來檢測:
- 如果專案基礎設施比較完善,那么可以使用分布式鏈路追蹤系統來追蹤每一條訊息,
- 如果專案初期,系統剛上線,那么可以利用訊息佇列的有序性來檢測是否有訊息丟失,
我們可以在Producer端發出的每一條訊息附加一個連續遞增的序號,然后在Consumer端檢測這個序號的連續性,如果沒有訊息丟失,Consumer收到的訊息的序號必然是連續遞增的,如果檢測到序號不連續,那么就是丟訊息了,還可以通過缺失的序號來確定丟失的是哪一條訊息,
針對這種檢測方法,有3條建議:
- 像Kafka和RocketMQ這樣的訊息佇列,它不保證訊息在Topic上的嚴格順序,只能保證訊息在磁區(佇列)上是有序的,所以我們在發訊息的時候必須要指定磁區,并且每個磁區單獨檢測訊息序號的連續性,
- 如果系統中有多個Producer實體,并且不好協調多個Producer之間的發送順序,那么也需要針對每個Producer分別生成各自的訊息序號,并且需要附加上Producer標識,在Consumer端按照每個Producer分別來檢測序號的連續性,
- Consumer實體的數量最好和磁區數量一致,做到Consumer和磁區一一對應,這樣比較方便在Consumer內檢測訊息序號的連續性,
訊息可靠傳遞
一條訊息從生產到消費完成的程序,可以分為三個階段:
- 生產階段:訊息在Producer創建出來,經過網路傳輸到Broker端,
- 存盤階段:訊息在Broker端存盤,如果是集群,訊息還會被復制到其他副本上,
- 消費階段:Consumer從Broker上拉取訊息,經過網路傳輸到Consumer上,
訊息生產階段
在生產階段,訊息佇列最常用的是請求-確認機制,來保證訊息的可靠傳遞:當代碼呼叫發訊息方法時,訊息佇列的客戶端會把訊息發送到Broker,Broker收到訊息后,會給客戶端回傳一個確認回應,表示訊息已經收到了,
只要Producer收到了Broker的確認回應,就可以保證訊息在生產階段不會丟失,有的訊息佇列會在長時間沒有收到發送確認回應后,自動重試,如果重試再失敗,就會以回傳值或者例外的方式告知用戶,
訊息存盤階段
在存盤階段正常情況下,只要Broker在正常運行,就不會出現丟失訊息的問題,但是如果Broker出現了故障,還是有可能會丟訊息,
如果對訊息的可靠性要求非常高,可以通過配置Broker引數來避免因為宕機丟訊息,
如果Broker是由多個節點組成的集群,那么需要將Broker集群配置成:至少將訊息發送到2個以上的節點后,再給客戶端回復發送確認回應,
訊息消費階段
消費階段采用和生產階段類似的請求-確認機制來保證訊息的可靠傳遞,客戶端從Broker拉取訊息后,執行用戶的消費業務邏輯,成功后,才會給Broker發送消費確認回應,
如果Borker沒有收到消費確認回應,下次拉訊息時還會回傳同一條訊息,確保訊息不回在網路傳輸程序中丟失,也不會因為客戶端在執行消費邏輯中出錯導致丟失,
我們需要注意,不要在收到訊息后就立即發送消費確認,而是應該在執行完所有消費業務邏輯之后,再發送消費確認,
作者:李潘 出處:http://wing011203.cnblogs.com/ 本文著作權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利,轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/546253.html
標籤:架構設計
