勇攀监控高峰-EMonitor之根因分析 背景
背景
阿里集團針對故障處理提出了“1/5/10”的目標-- 1 分鐘發現、5 分鐘定位、10 分鐘恢復,這對我們的定位能力提出了更高的要求。
EMonitor?是一款集成?Tracing?和?Metrics,服務于餓了么所有技術部門的一站式監控系統,其覆蓋了
- 前端監控、接入層監控;
- 業務 Trace 和 Metric 監控;
- 所有的中間件監控;
- 容器監控、物理機監控、機房網絡監控。
每日處理總數據量近 PB,每日寫入指標數據量上百 T,日均幾千萬的指標查詢量,內含上萬個圖表、數千個指標看板,并且已經將所有層的監控數據打通并串聯了起來。但是在故障來臨時,用戶仍然需要花費大量時間來查看和分析 EMonitor 上的數據
比如阿里本地生活的下單業務,涉及到諸多應用,每個應用諸多 SOA 服務之間錯綜復雜的調用關系,每個應用還依賴 DB、Redis、MQ 等等資源,在下單成功率下跌時,這些應用的負責人都要在 EMonitor 上查看指標曲線以及鏈路信息來進行人肉排障以自證清白,耗時耗力,所以自動化的根因分析必不可少。
根因分析建模
業界已經有好多在做根因分析的了,但是大都準確率不高,大部分還在 40% 到 70% 之間,從側面說明根因分析確實是一個難啃的骨頭。
根因分析看起來很龐大,很抽象,無從下手,從不同的角度(可能是表象)去看它,就可能走向不同的路。那如何才能透過表象來看到本質呢?
我這里并不會一開始就給你列出高大上的算法解決方案,而是要帶你重新認知根因分析要解決的問題到底是什么。其實好多人對要解決的問題都模糊不清,你只有對問題理解清楚了,才能有更好的方案來解決它。
要解決什么樣的問題
舉個例子:現有一個應用,擁有一堆容器資源,對外提供了諸多 SOA 服務或者 Http 服務,同時它也依賴了其他應用提供的服務,以及 DB 資源、Redis 資源、MQ 資源等等;那我們如何才能夠全面的掌控這個應用的健康狀況呢?
我們需要掌控:
- 掌控這個應用的所有入口服務的「耗時」和「狀態」
- 掌控每個入口服務之后每種操作的「耗時」和「狀態」
一個應用都有哪些入口?
- SOA 服務入口;
- Http 服務入口;
- MQ 消費消息入口;
- 定時 job 入口;
- 其他的一些入口。
進入每個入口之后,都可能會有一系列的如下?5 種操作和?1 種行為(下面的操作屬性都是以阿里本地生活的實際情況為例,并且都包含所在機房的屬性):
- DB 遠程操作:有 dal group、table、operation(比如select、update、insert等)、sql 的操作屬性;
- Redis 遠程操作:有 command 的操作屬性;
- MQ 遠程操作(向MQ中寫消息):有 exchange、routingKey、vhost 的操作屬性;
- RPC 遠程操作:有 遠程依賴的 appId、遠程 method 的操作屬性;
- Local 操作(即除了上述4種遠程操作之外的本地操作): 暫無屬性;
- 拋出異常的行為:有異常 name 的屬性。
那我們其實就是要去統計每個入口之后的 5 種操作的耗時情況以及狀態情況,以及拋出異常的統計情況。
針對遠程操作其實還要明細化,上述遠程操作的每一次耗時是包含如下 3 大部分:
- 客戶端建立連接、發送請求和接收響應的耗時;
- 網絡的耗時;
- 服務器端執行的耗時。
有了上述三要素,才能去確定遠程操作到底是哪出了問題,不過實際情況可能并沒有上述三要素。
故障的結論
有了上述數據的全面掌控,當一個故障來臨的時候,我們可以給出什么樣的結論?
- 哪些入口受到影響了?
- 受影響的入口的本地操作受到影響了?
-
受影響的入口的哪些遠程操作受到影響了?
- 具體是哪些遠程操作屬性受到影響了?
- 是客戶端到服務器端的網絡受到影響了?
- 是服務器端出了問題嗎?
- 受影響的入口都拋出了哪些異常?
上述的這些結論是可以做到非常高的準確性的,因為他們都是可以用數據來證明的。
然而第二類根因,卻是無法證明的:
- GC 問題;
- 容器問題。
他們一旦出問題,更多的表現是讓上述 5 種操作耗時變長,并且是沒法給出數據來明確證明他們和 5 種操作之間的關聯,只是以一種推測的方式來懷疑,從理論上來說這里就會存在誤定位的情況。
還有第三類更加無法證明的根因:
- 變更問題
昨天的變更或者當前的變更到底和當前的故障之間有沒有關聯,更是無法給出一個證明的,所以也只能是瞎推測。
我們可以明確的是 5 種操作的根因,還需要進一步去查看是否是上述第二類根因或者第三類根因,他們只能作為一些輔助結論,因為沒法給出嚴謹的數據證明。
根因分析實現
在明確了我們要解決的問題以及要求的故障結論之后,我們要采取什么樣的方案來解決呢?下面首先會介紹一個基本功能「指標下鉆分析」。
指標下鉆分析
一個指標,有多個 tag,當該指標總體波動時,指標下鉆分析能夠幫你分析出是哪些 tag 組合導致的波動。
比如客戶端的 DB 操作抖動了,利用指標下鉆分析就可以分析出
- 哪個機房抖動了?
- 哪個 dal group 抖動了?
- 哪張表抖動了?
- 哪種操作抖動了?
- 哪個 sql 抖動了?
再比如遠程 RPC 操作抖動了,利用指標下鉆分析就可以分析出
- 哪個機房抖動了?
- 哪個遠程 appId 抖動了?
- 哪個遠程 method 抖動了?
其實這個就是去年 AIOPS 競賽的題目,詳細見:
http://iops.ai/competition_detail/?competition_id=8&flag=1
通常的方案:
我們的方案:
針對去年的決賽題目,我們的這個方案的跑分達到了 0.95 以上,應該就在前三名了。
根因分析流程
有了指標下鉆分析功能之后,我們來看如何進行根因分析:
- 針對入口服務的響應時間和成功率判斷是否異常,若無異常則無根因可分析;
- 針對入口服務的 5 種操作進行指標下鉆分析,得出異常波動的操作類型有哪些;
-
然后到對應操作類型的指標中再次進行指標下鉆分析,得出該操作下:
- 哪些入口受到該操作的波動影響了?
- 哪些操作屬性異常波動了?
- 假如該操作是遠程操作,還要繼續深入服務器端進行分析:
假如你有遠程操作數據的 3 要素的話,那么是可以分析出:
- 客戶端建立連接、發送請求和接收響應耗時問題; - 網絡耗時問題; - 服務器端耗時問題。
假如沒有相關數據的話,那就只能相對來說進行推測了(準確率也會受到影響):
DAL 是我們的分庫分表的數據庫代理層,同時起到一些熔斷限流的作用,所以一條 SQL 執行時間會包含在 DAL 代理層的停留時間、以及在 DB 層的執行時間,利用指標下鉆分析,可以分析出如下的一些根因:
- 某個 table 的所有操作耗時抖動?- 某條sql操作耗時抖動?- 某臺具體DB實例抖動?- SQL的停留時間 or 執行時間抖動? - 比如客戶端的 RPC 操作來說,可以繼續遞歸到遠程 appId 的;- 針對受影響的這些入口使用指標下鉆分析,哪些異常也抖動了(有些異常一直在拋,但是跟本次故障無關);
- 再次查看上述抖動的操作是否是由 GC 問題、容器問題、變更問題等引起的。
落地情況
阿里本地生活的根因分析能力,1 個月內從產生根因分析的想法到實現方案上線到生產(不包括指標下鉆分析的實現,這個是之前就已經實現好的了),1 個月內在生產上實驗和優化并推廣開來,總共 2 個月內實現了從 0 到 1 并取得了如下成績
- 50 個詳細記載的案例中準確定位 48 次,準確率 96%;
- 最高一天執行定位 500 多次;
- 平均定位耗時 1 秒;
- 詳細的定位結果展示。
我們對定位準確性的要求如下:
- 要明確給出受到影響的入口服務有哪些;
- 每個受到影響的入口服務抖動的操作根因以及操作屬性都要正確;
每個入口服務抖動的根因很可能不一樣的,比如當前應用的 SOA1 是由于 Redis 操作抖動,當前應用的 SOA2 是由于遠程 RPC 依賴的其他 SOA3 抖動導致,SOA3 是由于 Redis 操作抖動導致;
- 客戶端操作耗時抖動到底是客戶端原因還是服務器端原因要保證正確;
- 容器問題時,要保證不能定位到錯誤的容器上。
準確率為什么這么高?
我認為主要是以下 3 個方面:
數據的完整度
假如是基于采樣鏈路去分析,必然會存在因為漏采導致誤判的問題。
我們分析的數據是全量鏈路數據轉化成的指標數據,不存在采樣的問題,同時在分析時可以直接基于指標進行快速分析,臨時查采樣的方式分析速度也是跟不上的。
建模的準確性
你的建模方案能回答出每個 SOA 服務抖動的根因分別是什么嗎?
絕大部分的建模方案可能都給不出嚴謹的數據證明,以 DB 是根因為例,他們的建模可能是 SOA 服務是一個指標,DB 操作耗時是一個指標,2 者之間是沒有任何關聯的,沒有數據關聯你就給不出嚴謹的證明,即沒法證明 DB 的這點抖動跟那個 SOA 服務之間到底有沒有關聯,然后就只能處于瞎推測的狀態,這里就必然存在誤判的情況。
而我們上述的建模是建立了相關的關聯,我們會統計每個入口后的每種操作的耗時,是可以給到嚴謹的數據證明。
異常判定的自適應性
比如 1 次 SOA 服務整體耗時 1s,遠程調用 RPC1 耗時 200ms,遠程調用 RPC2 耗時 500ms,到底是哪個 RPC 調用耗時抖動呢?耗時最長的嗎?超過一定閾值的 RPC 嗎?
假如你有閾值、同環比的限制,那么準確率一定不高的。我們的指標下鉆分析在解決此類問題的時候,是通過當前情況下的波動貢獻度的方式來計算,即使你耗時比較高,但是和之前正常情況波動不大,那么就不是波動的根因。
速度為什么這么快?
我認為主要是以下 2 方面的原因:
業內領先的時序數據庫 LinDB
根因分析需要對諸多指標的全量維度數據進行 group by 查詢,因此背后就需要依靠一個強大的分布式時序數據庫來提供實時的數據查詢能力。
LinDB 時序數據庫是我們阿里本地生活監控系統 E-Monitor 上一階段的自研產物,在查詢方面:
- 強悍的數據壓縮:時序數據原始數據量和實際存儲量之比達到 58:1,相同 PageCache 的內存可以比別的系統容納更多的數據;
- 高效的索引設計:索引的預過濾,改造版的 RoaringBitmap 之間的 and or 操作來進行高效的索引過濾;
- 單機內充分并行化的查詢機制:利用 akka 框架對整個查詢流程異步化。
整體查詢效率是 InfluxDB 的幾倍到幾百倍,詳細見文章
分布式時序數據庫 - LinDB ??https://zhuanlan.zhihu.com/p/35998778
指標下鉆分析算法的高效
- 我們不需要每個時間線都進行預測;
- 實際要計算的方案個數非常之少;
- 方案算分上可以適應于任何加減乘除之類的指標計算上,比如根因定位中的平均響應時間 = 總時間 / 總次數
SOA1 的平均響應時間 t1 和 SOA2 的平均響應時間 t2,SOA1 和 SOA2 的總體平均響應時間并不是 t1 和 t2 的算術平均而是加權平均,如果是加權平均,那么久需要多存儲一些額外的信息,并且需要進行額外的加權計算
實際案例
案例 1
故障現場如下,某個應用的 SOA 服務抖動上升:
直接點擊根因分析,就可以分析到如下結果
AppId1 的 SOA 服務在某個機房下抖動了
-
依賴的 AppId2 的 SOA 服務抖動
-
依賴的 AppId3 的 SOA 服務抖動
- 依賴的 AppId5 的本地處理和 Redis 操作耗時抖動
- 依賴的 AppId6 的本地處理和 Redis 操作耗時抖動
- 依賴的 AppId4 的本地處理和 Redis 操作耗時抖動
-
這里的本地處理包含獲取 Redis 連接對象 Jedis 的耗時,這一塊沒有耗時打點就導致劃分到本地處理上了,后續會進行優化。這里沒有給出詳細的 Redis 集群或者機器跟我們的實際情況有關,可以暫時忽略這一點。
點擊上面的每個應用,下面的表格都會列出所點擊應用的詳細故障信息
- 受影響的 SOA 服務有哪些,比如 AppId1 的 3 個 SOA 服務受到影響;
- 每個 SOA 服務抖動的根因,比如 AppId1 的 3 個 SOA 服務都受到 AppId2 的 1 個 SOA 服務的抖動影響;
- 表格中每一個鏈接都可以跳轉到對應的指標曲線監控面板上。
再比如點擊 AppId4,顯示如下:
AppId4 的 1 個 SOA 方法抖動
- 該方法的本地處理抖動(實際是獲取 Redis 連接對象 Jedis 的耗時抖動);
- 該方法依賴的 Redis 操作抖動;
- 該方法拋出 Redis 連接異常;
案例2
故障現場如下,某個應用的 SOA 服務抖動上升
點擊根因分析,就可以幫你分析到如下結果
AppId1 的 SOA 服務在某個機房下抖動了
-
依賴的 AppId2 的 SOA 服務抖動
- 依賴的 DB 服務抖動
-
依賴的 AppId3 的 SOA 服務抖動
-
依賴的 AppId2 的 SOA 服務抖動
- 依賴的 DB 服務抖動
-
點擊 AppId2,可以看下詳細情況,如下所示:
從表格中就可以看到,根因是 DB 的一臺實例抖動導致這個 dal group 所有操作抖動。
作者
李剛,網名乒乓狂魔,餓了么監控組研發專家,餓了么內部時序數據庫 LinDB 的項目負責人,餓了么根因分析項目負責人,目前致力于監控的智能分析領域以及下一代全景監控的體系化構建;
林濱(予譜),餓了么監控組前端工程師,現負責一站式監控系統 EMonitor 的前端開發,旨在將繁雜的數據以高可視化輸出。
原文鏈接
本文為云棲社區原創內容,未經允許不得轉載。
總結
以上是生活随笔為你收集整理的勇攀监控高峰-EMonitor之根因分析 背景的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 训练机器人看脸读“心”,真的靠谱吗?
- 下一篇: Java代码精简之道