再談訊息佇列技術-轉
再談訊息佇列技術
上週,我們舉辦了第二屆技術沙龍,我這邊主要演講了訊息佇列技術的議題,現分享給大家:
在我們團隊內部,隨著訊息應用中心(任務中心)的廣泛應用,有時候我們感覺不到訊息佇列的存在,但這不影響訊息佇列在高可用、分散式、高併發架構下的核心地位。
訊息佇列都應用到了哪些實際的應用場景中?
一、再談訊息佇列的應用場景
- 非同步處理:例如簡訊通知、終端狀態推送、App推送、使用者註冊等
- 資料同步:業務資料推送同步
- 重試補償:記賬失敗重試
- 系統解耦:通訊上下行、終端異常監控、分散式事件中心
- 流量消峰:秒殺場景下的下單處理
- 釋出訂閱:HSF的服務狀態變化通知、分散式事件中心
- 高併發緩衝:日誌服務、監控上報
但是,我們對訊息佇列的底層技術和原理還是不瞭解,那麼我們馬上開始吧…
二、訊息佇列的一些基本概念和簡單原理
1. Broker
Broker的概念來自與Apache ActiveMQ,通俗的講就是MQ的伺服器。
2. 訊息的生產者、消費者
訊息生產者Producer:傳送訊息到訊息佇列。
訊息消費者Consumer:從訊息佇列接收訊息。
3. 點對點訊息佇列模型
訊息生產者向一個特定的佇列傳送訊息,訊息消費者從該佇列中接收訊息;
訊息的生產者和消費者可以不同時處於執行狀態。
每一個成功處理的訊息都由訊息消費者簽收確認(Acknowledge)。如圖:
4. 釋出訂閱訊息模型-Topic
釋出訂閱訊息模型中,支援向一個特定的主題Topic釋出訊息,0個或多個訂閱者接收來自這個訊息主題的訊息。在這種模型下,釋出者和訂閱者彼此不知道對方。實際操作過程中,
釋出訂閱訊息模型中,支援向一個特定的主題Topic釋出訊息,0個或多個訂閱者接收來自這個訊息主題的訊息。在這種模型下,釋出者和訂閱者彼此不知道對方。實際操作過程中,
必須先訂閱,再傳送訊息,而後接收訂閱的訊息,這個順序必須保證。
5. 訊息的順序性保證
基於Queue訊息模型,利用FIFO先進先出的特性,可以保證訊息的順序性。
6. 訊息的ACK確認機制
即訊息的Ackownledge確認機制,
為了保證訊息不丟失,訊息佇列提供了訊息Acknowledge機制,即ACK機制,當Consumer確認訊息已經被消費處理,傳送一個ACK給訊息佇列,此時訊息佇列便可以刪除這個訊息了。如果Consumer當機/關閉,沒有傳送ACK,訊息佇列將認為這個訊息沒有被處理,會將這個訊息重新傳送給其他的Consumer重新消費處理。
7. 訊息的持久化
訊息的持久化,對於一些關鍵的核心業務來說是非常重要的,啟用訊息持久化後,訊息佇列當機重啟後,訊息可以從持久化儲存恢復,訊息不丟失,可以繼續消費處理。
8. 訊息的同步和非同步收發
同步:訊息的收發支援同步收發的方式。
同時還有另一種同步方式:同步收發場景下,訊息生產者和消費者雙向應答模式,例如:張三寫封信送到郵局中轉站,然後李四從中轉站獲得信,然後在寫一份回執信,放到中轉站,然後張三去取,當然張三寫信的時候就得寫明回信地址
訊息的接收如果以同步的方式(Pull)進行接收,如果佇列中為空,此時接收將處於同步阻塞狀態,會一直等待,直到訊息的到達。
非同步:訊息的收發同樣支援非同步方式:非同步傳送訊息,不需要等待訊息佇列的接收確認;非同步接收訊息,以Push的方式觸發訊息消費者接收訊息。
9. 訊息的事務支援
訊息的收發處理支援事務,例如:在任務中心場景中,一次處理可能涉及多個訊息的接收、處理,這處於同一個事務範圍內,如果一個訊息處理失敗,事務回滾,訊息重新回到佇列中。
三、我們對訊息佇列的實際使用
我們使用了兩種訊息佇列元件:
RabbitMQ:高可用、高可靠訊息應用場景,例如記賬失敗重試、通知服務,訊息不允許丟
Kafka:高效能訊息應用場景,例如日誌、監控,訊息允許丟失。
在此之上,我們封裝了訊息應用中心、日誌服務等核心元件和服務。那麼,訊息應用中心和日誌都用到了訊息佇列什麼技術? 乾貨來了…
1. 訊息應用中心
訊息應用中心(任務中心)使用了訊息佇列的非同步處理、資料同步、重試補償、系統解耦、流量消峰等特性。其中:
訊息應用中心(任務中心),支援RabbitMQ和Kafka兩種訊息通道,支援在任務後設資料層面設定
任務:就是一個包含了任務執行上下文的訊息,同時代表了非同步處理
任務傳送者(ITaskSender)傳送任務:訊息的生產者將任務訊息傳送的訊息佇列
任務型別:訊息佇列名稱,例如:HaKeepAcco***Queue,充電補償記賬佇列
訊息佇列:任務的臨時儲存
任務中心:任務集中處理,訊息消費者
任務處理完成:訊息Ack確認
任務的多級重試:多個重試訊息佇列,HaSysTaskStore2Queue
2. 日誌元件
日誌元件,使用了訊息佇列的高併發緩衝和釋出訂閱特性。其中:
日誌元件使用Kafka作為訊息通道,因為Kafka的效能好,吞吐量大, 可以容忍偶爾的訊息資料丟失
日誌元件使用釋出訂閱的訊息模型
日誌元件包含日誌服務SDK和日誌HSF服務,二者都是訊息的生產者Producer
日誌型別:訊息的Topic主題
日誌處理器:訊息的消費者、Topic的訂閱、日誌資料處理(Hbase\ES\其他)
3. RPC服務狀態變化通知
RPC服務狀態變化通知,使用了訊息佇列的釋出訂閱特性。其中:
RPC服務狀態變化通知,使用了RabbitMQ訊息佇列技術
使用釋出訂閱的訊息模型
Topic:RPCServiceState
RPCService.Proxy:RPC服務狀態變化訊息的訂閱者
RPC服務註冊、釋出:訊息的生產者,傳送RPC服務狀態變化訊息。
四、訊息佇列使用的最佳實踐
1. RabbitMQ的連線,底層都是Socket連線,長連線 or 短連線?
RabbitMQ每個在建立每個連線的同時,會自動建立一個監視執行緒來定時(預設60s)偵測連線的狀態,如果連線斷開,觸發ConnectionShutdown事件。
用長連線,還是用短連線??
傳送端:建議使用短連線,用完即釋放,避免長連線帶來的埠占用,因為傳送端無處不在,傳送操作短而急促。
接收端:建議使用長連線,時刻接收處理訊息,因為訊息的接收消費比較集中,接收操作久而彌堅。
2. 網路是有抖動的,連線的斷開是正常的,如何應對?
傳送端:傳送失敗重試
接收端:註冊ConnectionShutdown事件同時捕獲訊息接收異常,重新建立連線,接收消費訊息
3. RabbitMQ Exchange(Topic)模式下帶來的訊息佇列數量激增
只是建立了一個Exchange(Topic),為什麼會增加這麼多Queue。
因為,每個Topic的訂閱都是繫結一個Queue用作訊息的消費。
4. 需求的演變,訊息結構的變更,如何平滑過度?
訊息是byte[]陣列,我們將複雜物件訊息二進位制序列化。
接收到訊息後,我們將二進位制陣列反序列化為實體類。
當我們的實體類訊息體的結構發生變化後,因為受二進位制序列化處理的
影響,導致無法反序列化。
解決方案:
訊息體預留一些string型別的擴充套件欄位
訊息佇列版本化,支援多個版本的訊息體。
5. Kafka Consumer Group
同一Topic的一條訊息只能被同一個Group內的一個Consumer消費
多個Consumer Group可同時消費同一條訊息
6. 訊息的積壓
訊息的積壓產生的原因:訊息接收消費的速率低,傳送的速度>接收的速度。
訊息積壓後的影響:
訊息大量積壓後,當新的消費者連線上MQ並開始接收訊息時,傳送速率會大幅降低。
訊息佇列叢集的壓力增加,大量的訊息要持久化儲存和同步。
如何減少訊息積壓:快速消費訊息,同時保持訊息體的不要過大。
相關文章
- 訊息佇列雜談佇列
- 淺談訊息佇列佇列
- 談談訊息佇列的流派佇列
- 技術分享| 訊息佇列Kafka群集部署佇列Kafka
- 訊息佇列系列一:訊息佇列應用佇列
- 訊息佇列佇列
- 淺談訊息佇列及常見的訊息中介軟體佇列
- 訊息佇列(MQ)佇列MQ
- Kafka訊息佇列Kafka佇列
- RabbitMQ訊息佇列MQ佇列
- kafka 訊息佇列Kafka佇列
- POSIX訊息佇列佇列
- 訊息佇列(一)佇列
- 訊息佇列(二)佇列
- 訊息佇列二佇列
- [訊息佇列]rocketMQ佇列MQ
- [訊息佇列]RabbitMQ佇列MQ
- [Redis]訊息佇列Redis佇列
- 訊息佇列之Kafka——從架構技術重新理解Kafka佇列Kafka架構
- RabbitMQ 訊息佇列之佇列模型MQ佇列模型
- 全面理解Handler-1:理解訊息佇列,手寫訊息佇列佇列
- MQ訊息佇列_RabbitMQMQ佇列
- Java面試—訊息佇列Java面試佇列
- 訊息佇列二三事佇列
- rabbitmq訊息佇列原理MQ佇列
- 訊息佇列設計佇列
- 訊息佇列簡史佇列
- 訊息佇列之RabbitMQ佇列MQ
- 訊息佇列之RocketMQ佇列MQ
- 理解訊息佇列(MQ)佇列MQ
- 訊息佇列之 RabbitMQ佇列MQ
- 訊息佇列之 Kafka佇列Kafka
- 訊息佇列之 ActiveMQ佇列MQ
- 訊息佇列深入解析佇列
- 訊息佇列之 RocketMQ佇列MQ
- 分散式訊息佇列分散式佇列
- RabbitMQ 訊息佇列 配置MQ佇列
- 程式間通訊--訊息佇列佇列