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