RocketMQ 5.0 可觀測能力升級:Metrics 指標分析
作者:玄珏
從訊息的生命週期看可觀測能力
在進入主題之前先來看一下 RocketMQ 生產者、消費者和服務端互動的流程:
message produce and consume process
RocketMQ 的訊息是按照佇列的方式分割槽有序儲存的,這種佇列模型使得生產者、消費者和讀寫佇列都是多對多的對映關係,彼此之間可以無限水平擴充套件。對比傳統的訊息佇列如 RabbitMQ 是很大的優勢,尤其是在流式處理場景下能夠保證同一佇列的訊息被相同的消費者處理,對於批量處理、聚合處理更友好。
接下來我們來看一下訊息的整個生命週期中需要關注的重要節點:
message life cycle
首先是訊息傳送:傳送耗時是指一條訊息從生產者開始傳送到服務端接收到並儲存在硬碟上的時間。如果是定時訊息,需要到達指定的定時時間才能被消費者可見。
服務端收到訊息後需要根據訊息型別進行處理,對於定時/事務訊息只有到了定時時間/事務提交才對消費者可見。RocketMQ 提供了訊息堆積的特性,即訊息傳送到服務端後並不一定立即被拉取,可以按照客戶端的消費能力進行投遞。
從消費者的角度上看,有三個需要關注的階段:
- 拉取訊息:訊息從開始拉取到抵達客戶端的網路和服務端處理耗時;
- 訊息排隊:等待處理資源,即從訊息抵達客戶端到開始處理訊息;
- 訊息消費:從開始處理訊息到最後提交位點/返回 ACK。
訊息在生命週期的任何一個階段,都可以清晰地被定義並且被觀測到,這就是 RocketMQ 可觀測的核心理念。而本文要介紹的 Metrics 就踐行了這種理念,提供覆蓋訊息生命週期各個階段的監控埋點。藉助 Metrics 提供的原子能力我們可以搭建適合業務需要的監控系統:
- 日常巡檢與監控預警;
- 巨集觀趨勢/叢集容量分析;
- 故障問題診斷。
RocketMQ 4.x Metrics 實現 – Exporter
RocketMQ 團隊貢獻的 RocketMQ exporter 已被 Prometheus 官方的開源 Exporter 生態所收錄,提供了 Broker、Producer、Consumer 各個階段豐富的監控指標。
exporter metrics spec
Exporter 原理解析
RocketMQ expoter 獲取監控指標的流程如下圖所示,Expoter 通過 MQAdminExt 向 RocketMQ 叢集請求資料。獲取的資料轉換成 Prometheus 需要的格式,然後通過 /metics 介面暴露出來。
rocketmq exporter
隨著 RocketMQ 的演進,exporter 模式逐漸暴露出一些缺陷:
- 無法支援 RocketMQ 5.x 中新加入的 Proxy 等模組的可觀測需求;
- 指標定義不符合開源規範,難以和其他開源可觀測元件搭配使用;
- 大量 RPC 呼叫給 Broker 帶來額外的壓力;
- 拓展性差,增加/修改指標需要先修改 Broker 的 admin 介面。
為解決以上問題,RocketMQ 社群決定擁抱社群標準,在 RocketMQ 5.x 中推出了基於 OpenTelemtry 的 Metrics 方案。
RocketMQ 5.x 原生 Metrics 實現
基於 OpenTelemtry 的 Metrics
OpenTelemetry 是 CNCF 的一個可觀測性專案,旨在提供可觀測性領域的標準化方案,解決觀測資料的資料模型、採集、處理、匯出等的標準化問題,提供與三方 vendor 無關的服務。
在討論新的 Metrics 方案時 RocketMQ 社群決定遵守 OpenTelemetry 規範,完全重新設計新 metrics 的指標定義:資料型別選用相容 Promethues 的 Counter、Guage、Histogram,並且遵循 Promethues 推薦的指標命名規範,不相容舊有的 rocketmq-exporter 指標。新指標覆蓋 broker、proxy、producer、consumer 等各個 module,對訊息生命週期的全階段提供監控能力。
指標上報方式
我們提供了三種指標上報的方式:
- Pull 模式:適合自運維 K8s 和 Promethues 叢集的使用者;
- Push 模式:適合希望對 metrics 資料做後處理或接入雲廠商的可觀測服務的使用者;
- Exporter 相容模式:適合已經在使用 Exporter 和有跨資料中心(或其他網路隔離環境)傳輸 metrics 資料需求的使用者。
Pull
Pull 模式旨在與 Prometheus 相容。在 K8s 部署環境中無需部署額外的元件,prometheus 可以通過社群提供的 K8s 服務發現機制(建立 PodMonitor、ServiceMonitor CDR)自動獲取要拉取的 broker/proxy 列表,並從他們提供的 endpoint 中拉取 metrics 資料。
pull mode
Push
OpenTelemetry 推薦使用 Push 模式,這意味著它需要部署一個 collector 來傳輸指標資料。
push mode
OpenTelemetry 官方提供了 collector 的實現,支援對指標做自定義操作如過濾、富化,可以利用社群提供的外掛實現自己的 collector。並且雲廠商提供的可觀測服務(如 AWS CloudWatch、阿里雲 SLS)大多已經擁抱了 OpenTelemetry 社群,可以直接將資料推送到它們提供的 collector 中,無需額外的元件進行橋接。
OpenTelemetry collector
相容 RocketMQ Exporter
新的 Metrics 也提供對 RocketMQ Exporter 的相容,現在使用 exporter 的使用者無需變更部署架構即可接入新 Metrics。而且控制面應用(如 Promethues)和資料面應用(如 RocketMQ)有可能隔離部署。因此藉助 Exporter 作為代理來獲取新的 Metrics 資料也不失為一種好的選擇。
RocketMQ 社群在 Exporter 中嵌入了一個 OpenTelemetry collector 實現,Broker 將 Metrics 資料匯出到 Exporter,Exporter 提供了一個新的 endpoint(下圖中的 metrics-v2)供 Prometheus 拉取。
exporter mode
構建監控體系最佳實踐
豐富的指標覆蓋與對社群標準的遵循使得可以輕而易舉的藉助 RocketMQ 的 Metrics 能力構建出適合業務需求的監控體系,這個章節主要以一個典型的流程介紹構建監控體系的最佳實踐:
叢集監控/巡檢 -> 觸發告警 -> 排查分析。
叢集狀態監控與巡檢
我們將指標採集到 Promethues 後就可以基於這些指標配置監控,這裡給出一些示例:
介面監控:
監控介面呼叫情況,可以據此快速抓出異常的請求對症下藥
下圖給出一些相關示例:所有 RPC 的耗時(avg、pt90、pt99 等)、成功率、失敗原因、介面呼叫與返回值分佈情況等。
rpc metrics
客戶端監控:
監控客戶端的使用情況,發現非預期的客戶端使用如超大訊息傳送、客戶端上下線、客戶端版本治理等。
下圖給出一些相關示例:客戶端連線數、客戶端語言/版本分佈、傳送的訊息大小/型別分佈。
client metrics
Broker 監控:
監控 Broker 的水位和服務質量,及時發現叢集容量瓶頸。
下圖給出一些相關示例:Dispatch 延遲、訊息保留時間、執行緒池排隊、訊息堆積情況。
broker metrics
以上的示例只是 Metrics 的冰山一角,需要根據業務需要靈活組合不同的指標配置監控與巡檢。
告警配置
有了完善的監控就可以對需要關注的指標配置告警,比如可以配置 Broker 監控中 Dispatch 延遲這個指標的告警:
broker alert
收到告警後可以聯動監控檢視具體原因,關聯傳送介面的失敗率可以發現有 1.7% 的消費傳送失敗,對應的報錯是沒有建立訂閱組:
promblem analysis
問題排查分析
最後以訊息堆積這個場景為例來看一下如何基於 Metrics 分析線上問題。
從訊息生命週期看堆積問題
正如本文開篇所述,排查 RocketMQ 的問題需要結合訊息的生命週期綜合分析,如果片面的認定是服務端/客戶端的故障未免會誤入歧途。
對於堆積問題,我們主要關注訊息生命週期中的兩個階段:
- 就緒訊息:就緒訊息是可供消費但還未被拉取的訊息,即在服務端堆積的訊息;
- 處理中訊息:處理中的訊息是被客戶端拉取但是還未被消費的訊息。
consume lag
多維度指標分析堆積問題
對於堆積問題,RocketMQ 提供了消費延遲相關指標 rocketmq_consumer_lag_latency
可以基於這個指標配置告警。告警的閾值需要根據當前業務對消費延遲的容忍程度靈活指定。
觸發告警後就需要對訊息堆積在還是就緒訊息和處理中訊息進行分析,RocketMQ 提供了 rocketmq_consumer_ready_messages
和 rocketmq_consumer_inflight_messages
這兩個指標,結合其他消費相關指標與客戶端配置綜合分析即可判斷出訊息堆積的根因:
- case 1:就緒訊息持續上漲,處理中訊息達到客戶端堆積上限
這是最常見的堆積場景,客戶端處理中的訊息量 rocketmq_consumer_inflight_messages
達到了客戶端配置的閾值,即消費者的消費能力低於訊息傳送量。如果業務要求儘可能實時的消費訊息就需要增加消費者機器數量,如果業務對訊息延遲不是很敏感可以等待業務高峰過去後再消化堆積的訊息。
- case 2:就緒訊息幾乎為 0,處理中訊息持續上漲
這個 case 多出現在使用 RocketMQ 4.x 客戶端的場景,此時消費位點是順序提交的,如果某條訊息的消費卡住會導致位點無法提交。看起來的現象是訊息在客戶端大量堆積,即處理中訊息持續上漲。可以結合消費軌跡和 rocketmq_process_time
這個指標抓出消費慢的訊息分析上下游鏈路,找到根因優化消費邏輯。
- case 3: 就緒訊息持續上漲,處理中訊息幾乎為 0
此種場景說明客戶端沒有拉取到訊息,一般有如下幾種情況:
-
鑑權問題:檢查 ACL 配置,如果使用公有云產品請檢查 AK、SK 配置;
-
消費者 hang 住:嘗試列印執行緒堆疊或 gc 資訊判斷是否是程序卡死;
-
服務端響應慢:結合 RPC 相關指標檢視拉取訊息介面呼叫量與耗時、硬碟讀寫延遲。檢查是否為服務端問題,如硬碟 IOPS 被打滿了等等。