RocketMQ 千錘百煉 - 哈啰在分布式消息治理和微服務治理中的實踐
背景
哈啰已進化為包括兩輪出行(哈啰單車、哈啰助力車、哈啰電動車、小哈換電)、四輪出行(哈啰順風車、全網叫車、哈啰打車)等的綜合化移動出行平臺,并向酒店、到店團購等眾多本地生活化生態探索。
隨著公司業務的不斷發展,流量也在不斷增長。我們發現生產中的一些重大事故,往往是被突發的流量沖跨的,對流量的治理和防護,保障系統高可用就尤為重要。
本文就哈啰在消息流量和微服務調用的治理中踩過的坑、積累的經驗進行分享。
聊聊治理這件事
開始之前先聊聊治理這件事情,下面是老梁個人理解:
治理在干一件什么事?
讓我們的環境變得美好一些
需要知道哪些地方還不夠好?
以往經驗
用戶反饋
業內對比
還需要知道是不是一直都是好的?
監控跟蹤
告警通知
不好的時候如何再讓其變好?
治理措施
應急方案
目錄
打造分布式消息治理平臺
RocketMQ 實戰踩坑和解決
打造微服務高可用治理平臺
背景
裸奔的 RabbitMQ
公司之前使用 RabbitMQ ,下面在使用 RabbitMQ 時的痛點,其中很多事故由于 RabbitMQ 集群限流引起的。
積壓過多是清理還是不清理?這是個問題,我再想想。
積壓過多觸發集群流控?那是真的影響業務了。
想消費前兩天的數據?請您重發一遍吧。
要統計哪些服務接入了?您要多等等了,我得去撈IP看看。
有沒有使用風險比如大消息?這個我猜猜。
裸奔的服務
曾經有這么一個故障,多個業務共用一個數據庫。在一次晚高峰流量陡增,把數據庫打掛了。
數據庫單機升級到最高配依然無法解決
重啟后緩一緩,不一會就又被打掛了
如此循環著、煎熬著、默默等待著高峰過去
思考:無論消息還是服務都需要完善的治理措施
打造分布式消息治理平臺
設計指南
哪些是我們的關鍵指標,哪些是我們的次要指標,這是消息治理的首要問題。
設計目標
旨在屏蔽底層各個中間件( RocketMQ / Kafka )的復雜性,通過唯一標識動態路由消息。同時打造集資源管控、檢索、監控、告警、巡檢、容災、可視化運維等一體化的消息治理平臺,保障消息中間件平穩健康運行。
消息治理平臺設計需要考慮的點
提供簡單易用 API
有哪些關鍵點能衡量客戶端的使用沒有安全隱患
有哪些關鍵指標能衡量集群健康不健康
有哪些常用的用戶/運維操作將其可視化
有哪些措施應對這些不健康
盡可能簡單易用
設計指南
把復雜的問題搞簡單,那是能耐。
極簡統一 API
提供統一的 SDK 封裝了( Kafka / RocketMQ )兩種消息中間件。
一次申請
主題消費組自動創建不適合生產環境,自動創建會導致失控,不利于整個生命周期管理和集群穩定。需要對申請流程進行控制,但是應盡可能簡單。例如:一次申請各個環境均生效、生成關聯告警規則等。
客戶端治理
設計指南
監控客戶端使用是否規范,找到合適的措施治理
場景回放
場景一 瞬時流量與集群的流控
假設現在集群 Tps 有 1 萬,瞬時翻到 2 萬甚至更多,這種過度陡增的流量極有可能引發集群流控。針對這類場景需監控客戶端的發送速度,在滿足速度和陡增幅度閾值后將發送變的平緩一些。
場景二 大消息與集群抖動
當客戶端發送大消息時,例如:發送幾百KB甚至幾兆的消息,可能造成 IO 時間過長與集群抖動。針對這類場景治理需監控發送消息的大小,我們采取通過事后巡檢的方式識別出大消息的服務,推動使用同學壓縮或重構,消息控制在 10KB 以內。
場景三 過低客戶端版本
隨著功能的迭代 SDK 的版本也會升級,變更除了功能外還有可能引入風險。當使用過低的版本時一個是功能不能得到支持,另外一個是也可能存在安全隱患。為了解 SDK 使用情況,可以采取將 SDK 版本上報,通過巡檢的方式推動使用同學升級。
場景四 消費流量摘除和恢復
消費流量摘除和恢復通常有以下使用場景,第一個是發布應用時需要先摘流量,另外一個是問題定位時希望先把流量摘除掉再去排查。為了支持這種場景,需要在客戶端監聽摘除/恢復事件,將消費暫停和恢復。
場景五 發送/消費耗時檢測
發送/消費一條消息用了多久,通過監控耗時情況,巡檢摸排出性能過低的應用,針對性推動改造達到提升性能的目的。
場景六 提升排查定位效率
在排查問題時,往往需要檢索發了什么消息、存在哪里、什么時候消費的等消息生命周期相關的內容。這部分可以通過 msgId 在消息內部將生命周期串聯起來。另外是通過在消息頭部埋入 rpcId / traceId 類似鏈路標識,在一次請求中將消息串起來。
治理措施提煉
需要的監控信息
發送/消費速度
發送/消費耗時
消息大小
節點信息
鏈路標識
版本信息
常用治理措施
定期巡檢:有了埋點信息可以通過巡檢將有風險的應用找出來。例如發送/消費耗時大于 800 ms、消息大小大于 10 KB、版本小于特定版本等。
發送平滑:例如檢測到瞬時流量滿足 1 萬而且陡增了 2 倍以上,可以通過預熱的方式將瞬時流量變的平滑一些。
消費限流:當第三方接口需要限流時,可以對消費的流量進行限流,這部分可以結合高可用框架實現。
消費摘除:通過監聽摘除事件將消費客戶端關閉和恢復。
主題/消費組治理
設計指南
監控主題消費組資源使用情況
場景回放
場景一 消費積壓對業務的影響
有些業務場景對消費堆積很敏感,有些業務對積壓不敏感,只要后面追上來消費掉即可。例如單車開鎖是秒級的事情,而信息匯總相關的批處理場景對積壓不敏感。通過采集消費積壓指標,對滿足閾值的應用采取實時告警的方式通知到應用負責的同學,讓他們實時掌握消費情況。
場景二 消費/發送速度的影響
發送/消費速度跌零告警?有些場景速度不能跌零,如果跌零意味著業務出現異常。通過采集速度指標,對滿足閾值的應用實時告警。
場景三 消費節點掉線
消費節點掉線需要通知給應用負責的同學,這類需要采集注冊節點信息,當掉線時能實時觸發告警通知。
場景四 發送/消費不均衡
發送/消費的不均衡往往影響其性能。記得有一次咨詢時有同學將發送消息的key設置成常量,默認按照 key 進行 hash 選擇分區,所有的消息進入了一個分區里,這個性能是無論如何也上不來的。另外還要檢測各個分區的消費積壓情況,出現過度不均衡時觸發實時告警通知。
治理措施提煉
需要的監控信息
發送/消費速度
發送分區詳情
消費各分區積壓
消費組積壓
注冊節點信息
常用治理措施
實時告警:對消費積壓、發送/消費速度、節點掉線、分區不均衡進行實時告警通知。
提升性能:對于有消費積壓不能滿足需求,可以通過增加拉取線程、消費線程、增加分區數量等措施加以提升。
自助排查:提供多維度檢索工具,例如通過時間范圍、msgId 檢索、鏈路系統等多維度檢索消息生命周期。
集群健康治理
設計指南
度量集群健康的核心指標有哪些?
場景回放
場景一 集群健康檢測
集群健康檢測回答一個問題:這個集群是不是好的。通過檢測集群節點數量、集群中每個節點心跳、集群寫入Tps水位、集群消費Tps水位都是在解決這個問題。
場景二 集群的穩定性
集群流控往往體現出集群性能的不足,集群抖動也會引發客戶端發送超時。通過采集集群中每個節點心跳耗時情況、集群寫入Tps水位的變化率來掌握集群是否穩定。
場景三 集群的高可用
高可用主要針對極端場景中導致某個可用區不可用、或者集群上某些主題和消費組異常需要有一些針對性的措施。例如:MQ 可以通過同城跨可用區主從交叉部署、動態將主題和消費組遷移到災備集群、多活等方式進行解決。
治理措施提煉
需要的監控信息
集群節點數量采集
集群節點心跳耗時
集群寫入 Tps 的水位
集群消費 Tps 的水位
集群寫入 Tps 的變化率
常用治理措施
定期巡檢:對集群 Tps 水位、硬件水位定期巡檢。
容災措施:同城跨可用區主從交叉部署、容災動態遷移到災備集群、異地多活。
集群調優:系統版本/參數、集群參數調優。
集群分類:按業務線分類、按核心/非核心服務分類。
最核心指標聚焦
如果說這些關鍵指標中哪一個最重要?我會選擇集群中每個節點的心跳檢測,即:響應時間( RT ),下面看看影響 RT 可能哪些原因。
關于告警
監控指標大多是秒級探測
觸發閾值的告警推送到公司統一告警系統、實時通知
巡檢的風險通知推送到公司巡檢系統、每周匯總通知
消息平臺圖示
架構圖
看板圖示
多維度:集群維度、應用維度
全聚合:關鍵指標全聚合
RocketMQ 實戰中踩過的坑和解決方案
行動指南
我們總會遇到坑,遇到就把它填了。
1. RocketMQ 集群 CPU 毛刺
問題描述
RocketMQ 從節點、主節點頻繁 CPU 飆高,很明顯的毛刺,很多次從節點直接掛掉了。
只有系統日志有錯誤提示
2020-03-16T17:56:07.505715+08:00 VECS0xxxx kernel:[] ? __alloc_pages_nodemask+0x7e1/0x9602020-03-16T17:56:07.505717+08:00 VECS0xxxx kernel: java: page allocation failure. order:0, mode:0x202020-03-16T17:56:07.505719+08:00 VECS0xxxx kernel: Pid: 12845, comm: java Not tainted 2.6.32-754.17.1.el6.x86_64 #12020-03-16T17:56:07.505721+08:00 VECS0xxxx kernel: Call Trace:2020-03-16T17:56:07.505724+08:00 VECS0xxxx kernel:[] ? __alloc_pages_nodemask+0x7e1/0x9602020-03-16T17:56:07.505726+08:00 VECS0xxxx kernel: [] ? dev_queue_xmit+0xd0/0x3602020-03-16T17:56:07.505729+08:00 VECS0xxxx kernel: [] ? ip_finish_output+0x192/0x3802020-03-16T17:56:07.505732+08:00 VECS0xxxx kernel: [] ?
各種調試系統參數只能減緩但是不能根除,依然毛刺超過 50%
解決方案
將集群所有系統升級從 centos 6 升級到 centos 7 ,內核版本也從從 2.6 升級到 3.10 ,CPU 毛刺消失。
2. RocketMQ 集群線上延遲消息失效
問題描述
RocketMQ 社區版默認本支持 18 個延遲級別,每個級別在設定的時間都被會消費者準確消費到。為此也專門測試過消費的間隔是不是準確,測試結果顯示很準確。然而,如此準確的特性居然出問題了,接到業務同學報告線上某個集群延遲消息消費不到,詭異!
解決方案
將" delayOffset.json "和" consumequeue / SCHEDULE_TOPIC_XXXX "移到其他目錄,相當于刪除;逐臺重啟 broker 節點。重啟結束后,經過驗證,延遲消息功能正常發送和消費。
打造微服務高可用治理平臺
設計指南
哪些是我們的核心服務,哪些是我們的非核心服務,這是服務治理的首要問題
設計目標
服務能應對突如其來的陡增流量,尤其保障核心服務的平穩運行。
應用分級和分組部署
應用分級
根據用戶和業務影響兩個緯度來進行評估設定的,將應用分成了四個等級。
業務影響:應用故障時影響的業務范圍
用戶影響:應用故障時影響的用戶數量
S1:核心產品,產生故障會引起外部用戶無法使用或造成較大資損,比如主營業務核心鏈路,如單車、助力車開關鎖、順風車的發單和接單核心鏈路,以及其核心鏈路強依賴的應用。
S2: 不直接影響交易,但關系到前臺業務重要配置的管理與維護或業務后臺處理的功能。
S3: 服務故障對用戶或核心產品邏輯影響非常小,且對主要業務沒影響,或量較小的新業務;面向內部用戶使用的重要工具,不直接影響業務,但相關管理功能對前臺業務影響也較小。
S4: 面向內部用戶使用,不直接影響業務,或后續需要推動下線的系統。
分組部署
S1 服務是公司的核心服務,是重點保障的對象,需保障其不被非核心服務流量意外沖擊。
S1 服務分組部署,分為 Stable 和 Standalone 兩套環境
非核心服務調用 S1 服務流量路由到 Standalone 環境
S1 服務調用非核心服務需配置熔斷策略
多種限流熔斷能力建設
我們建設的高可用平臺能力
部分限流效果圖
預熱圖示
排隊等待
預熱+排隊
高可用平臺圖示
中間件全部接入
動態配置實時生效
每個資源和 IP 節點詳細流量
總結
哪些是我們的關鍵指標,哪些是我們的次要指標,這是消息治理的首要問題
哪些是我們的核心服務,哪些是我們的非核心服務,這是服務治理的首要問題
源碼&實戰 是一種比較好的工作學習方法。