勇攀監控高峰 | EMonitor 之根因分析

阿里巴巴中介軟體發表於2020-07-20

背景



阿里集團針對故障處理提出了“1/5/10”的目標-- 1 分鐘發現、5 分鐘定位、10 分鐘恢復,這對我們的定位能力提出了更高的要求。


EMonitor 是一款整合 TracingMetrics,服務於餓了麼所有技術部門的一站式監控系統,其覆蓋了:
1、前端監控、接入層監控;
2、業務 Trace 和 Metric 監控;
3、所有的中介軟體監控;
4、容器監控、物理機監控、機房網路監控。

每日處理總資料量近 PB,每日寫入指標資料量上百 T,日均幾千萬的指標查詢量,內含上萬個圖表、數千個指標看板,並且已經將所有層的監控資料打通並串聯了起來。但是在故障來臨時,使用者仍然需要花費大量時間來檢視和分析 EMonitor 上的資料。

比如阿里本地生活的下單業務,涉及到諸多應用,每個應用諸多 SOA 服務之間錯綜複雜的呼叫關係,每個應用還依賴 DB、Redis、MQ 等等資源,在下單成功率下跌時,這些應用的負責人都要在 EMonitor 上檢視指標曲線以及鏈路資訊來進行人肉排障以自證清白,耗時耗力,所以自動化的根因分析必不可少。


根因分析建模



業界已經有好多在做根因分析的了,但是大都準確率不高,大部分還在 40% 到 70% 之間,從側面說明根因分析確實是一個難啃的骨頭。


根因分析看起來很龐大,很抽象,無從下手,從不同的角度(可能是表象)去看它,就可能走向不同的路。那如何才能透過表象來看到本質呢?

我這裡並不會一開始就給你列出高大上的演算法解決方案,而是要帶你重新認知根因分析要解決的問題到底是什麼。其實好多人對要解決的問題都模糊不清,你只有對問題理解清楚了,才能有更好的方案來解決它。

要解決什麼樣的問題


舉個例子:現有一個應用,擁有一堆容器資源,對外提供了諸多 SOA 服務或者 Http 服務,同時它也依賴了其他應用提供的服務,以及 DB 資源、Redis 資源、MQ 資源等等,那我們如何才能夠全面的掌控這個應用的健康狀況呢?

我們需要掌控:
1、掌控這個應用的所有入口服務的「耗時」和「狀態」
2、掌控每個入口服務之後每種操作的「耗時」和「狀態」

一個應用都有哪些入口?

1、SOA 服務入口;

2、Http 服務入口;

3、MQ 消費訊息入口;

4、定時 job 入口;

5、其他的一些入口。

進入每個入口之後,都可能會有一系列的如下 5 種操作和 1 種行為(下面的操作屬性都是以阿里本地生活的實際情況為例,並且都包含所在機房的屬性):
1、DB 遠端操作:有 dal group、table、operation(比如select、update、insert等)、sql 的操作屬性;
2、Redis 遠端操作:有 command 的操作屬性;
3、MQ 遠端操作(向MQ中寫訊息):有 exchange、routingKey、vhost 的操作屬性;
4、RPC 遠端操作:有 遠端依賴的 appId、遠端 method 的操作屬性;
5、Local 操作(即除了上述4種遠端操作之外的本地操作): 暫無屬性;
6、丟擲異常的行為:有異常 name 的屬性。

那我們其實就是要去統計每個入口之後的 5 種操作的耗時情況以及狀態情況,以及丟擲異常的統計情況。

針對遠端操作其實還要明細化,上述遠端操作的每一次耗時是包含如下 3 大部分:
1、客戶端建立連線、傳送請求和接收響應的耗時;
2、網路的耗時;
3、伺服器端執行的耗時。

有了上述三要素,才能去確定遠端操作到底是哪出了問題,不過實際情況可能並沒有上述三要素。

故障的結論


有了上述資料的全面掌控,當一個故障來臨的時候,我們可以給出什麼樣的結論?
1、哪些入口受到影響了?
2、受影響的入口的本地操作受到影響了?
3、受影響的入口的哪些遠端操作受到影響了?

  • 具體是哪些遠端操作屬性受到影響了?

  • 是客戶端到伺服器端的網路受到影響了?

  • 是伺服器端出了問題嗎?

4、受影響的入口都丟擲了哪些異常?

上述的這些結論是可以做到非常高的準確性的,因為他們都是可以用資料來證明的。

然而第二類根因,卻是無法證明的:
1、GC 問題;
2、容器問題。

他們一旦出問題,更多的表現是讓上述 5 種操作耗時變長,並且是沒法給出資料來明確證明他們和 5 種操作之間的關聯,只是以一種推測的方式來懷疑,從理論上來說這裡就會存在誤定位的情況。

還有第三類更加無法證明的根因--變更問題

昨天的變更或者當前的變更到底和當前的故障之間有沒有關聯,更是無法給出一個證明的,所以也只能是瞎推測。

我們可以明確的是 5 種操作的根因,還需要進一步去檢視是否是上述第二類根因或者第三類根因,他們只能作為一些輔助結論,因為沒法給出嚴謹的資料證明。


根因分析實現



在明確了我們要解決的問題以及要求的故障結論之後,我們要採取什麼樣的方案來解決呢?下面首先會介紹一個基本功能「指標下鑽分析」。


指標下鑽分析


一個指標,有多個 tag,當該指標總體波動時,指標下鑽分析能夠幫你分析出是哪些 tag 組合導致的波動。

比如客戶端的 DB 操作抖動了,利用指標下鑽分析就可以分析出:
1、哪個機房抖動了?
2、哪個 dal group 抖動了?
3、哪張表抖動了?
4、哪種操作抖動了?
5、哪個 sql 抖動了?

再比如遠端 RPC 操作抖動了,利用指標下鑽分析就可以分析出:
1、哪個機房抖動了?
2、哪個遠端 appId 抖動了?
3、哪個遠端 method 抖動了?

其實這個就是去年 AIOPS 競賽的題目,詳細見:

通常的方案:
1、對每個時序曲線都要進行資料預測,拿到預測值;
2、針對每個方案根據實際值和預測值的差異算出一個方案分數;
3、遍歷所有可能性方案,挑選出分數最高的方案(透過蒙特卡洛樹搜尋進行剪枝最佳化)。

我們的方案:
1、確定整體的波動範圍
2、定計算範圍 = 該波動範圍 + 前面一段正常範圍,在計算範圍內算出每根時間線的波動值(比如波動的方差,實際肯定不會這麼簡單,有很多的最佳化點);
3、對所有時間曲線進行一些過濾(比如和整體抖動方法相反,整體都向上抖動,它向下抖動);
4、對過濾後的時間曲線按照波動值進行 KMeans 聚類
5、從排名靠前的分類中挑選出方案,為每個方案計算方案分數(這個方案個數就非常之少了);
6、得出分數最高的方案

針對去年的決賽題目,我們的這個方案的跑分達到了 0.95 以上,應該就在前三名了。

根因分析流程


有了指標下鑽分析功能之後,我們來看如何進行根因分析:

勇攀監控高峰 | EMonitor 之根因分析

1、針對入口服務的響應時間和成功率判斷是否異常,若無異常則無根因可分析;

2、針對入口服務的 5 種操作進行指標下鑽分析,得出異常波動的操作型別有哪些;

3、然後到對應操作型別的指標中再次進行指標下鑽分析,得出該操作下:

a.哪些入口受到該操作的波動影響了?

b.哪些操作屬性異常波動了?

c.假如該操作是遠端操作,還要繼續深入伺服器端進行分析:


假如你有遠端運算元據的 3 要素的話,那麼是可以分析出:

  • 客戶端建立連線、傳送請求和接收響應耗時問題;

  • 網路耗時問題;

  • 伺服器端耗時問題。


假如沒有相關資料的話,那就只能相對來說進行推測了(準確率也會受到影響):

  • 假如伺服器端耗時正常的話,那就相對劃分為客戶端傳送請求或接收響應耗時是根因;

  • 假如伺服器端耗時異常抖動的話,那麼就需要到伺服器端進行深入分析;

  • 比如 DB 操作來說,可以繼續深入到 DAL 層面分析。


        DAL 是我們的分庫分表的資料庫代理層,同時起到一些熔斷限流的作用,所以一條 SQL 執行時間會包含在 DAL 代理層的停留時間、以及在 DB 層的執行時間,利用指標下鑽分析,可以分析出如下的一些根因:

  • 某個 table 的所有操作耗時抖動?

  • 某條 SQL 操作耗時抖動?

  • 某臺具體 DB 例項抖動?

  • SQL 的停留時間 or 執行時間抖動?


  • 比如客戶端的 RPC 操作來說,可以繼續遞迴到遠端 appId 的根因分析流程:


4、針對受影響的這些入口使用指標下鑽分析,哪些異常也抖動了(有些異常一直在拋,但是跟本次故障無關);
5、再次檢視上述抖動的操作是否是由 GC 問題、容器問題、變更問題等引起的。


落地情況



阿里本地生活的根因分析能力,1 個月內從產生根因分析的想法到實現方案上線到生產(不包括指標下鑽分析的實現,這個是之前就已經實現好的了),1 個月內在生產上實驗和最佳化並推廣開來,總共 2 個月內實現了從 0 到 1 並取得了如下成績:

1、50 個詳細記載的案例中準確定位 48 次,準確率 96%;

2、最高一天執行定位 500 多次;

3、平均定位耗時 1 秒;

4、詳細的定位結果展示。

我們對定位準確性的要求如下:
1、要明確給出受到影響的入口服務有哪些;
2、每個受到影響的入口服務抖動的操作根因以及操作屬性都要正確,每個入口服務抖動的根因很可能不一樣的,比如當前應用的 SOA1 是由於 Redis 操作抖動,當前應用的 SOA2 是由於遠端 RPC 依賴的其他 SOA3 抖動導致,SOA3 是由於 Redis 操作抖動導致。
3、客戶端操作耗時抖動到底是客戶端原因還是伺服器端原因要保證正確;
4、容器問題時,要保證不能定位到錯誤的容器上。


準確率為什麼這麼高?



我認為主要是以下 3 個方面:


1、資料的完整度

假如是基於取樣鏈路去分析,必然會存在因為漏採導致誤判的問題。

我們分析的資料是全量鏈路資料轉化成的指標資料,不存在取樣的問題,同時在分析時可以直接基於指標進行快速分析,臨時查取樣的方式分析速度也是跟不上的。

2、建模的準確性

你的建模方案能回答出每個 SOA 服務抖動的根因分別是什麼嗎?

絕大部分的建模方案可能都給不出嚴謹的資料證明,以 DB 是根因為例,他們的建模可能是 SOA 服務是一個指標,DB 操作耗時是一個指標,2 者之間是沒有任何關聯的,沒有資料關聯你就給不出嚴謹的證明,即沒法證明 DB 的這點抖動跟那個 SOA 服務之間到底有沒有關聯,然後就只能處於瞎推測的狀態,這裡就必然存在誤判的情況。

而我們上述的建模是建立了相關的關聯,我們會統計每個入口後的每種操作的耗時,是可以給到嚴謹的資料證明。

3、異常判定的自適應性

比如 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   :

指標下鑽分析演算法的高效


  • 我們不需要每個時間線都進行預測;
  • 實際要計算的方案個數非常之少;
  • 方案算分上可以適應於任何加減乘除之類的指標計算上,比如根因定位中的平均響應時間 = 總時間 / 總次數

SOA1 的平均響應時間 t1 和 SOA2 的平均響應時間 t2,SOA1 和 SOA2 的總體平均響應時間並不是 t1 和 t2 的算術平均而是加權平均,如果是加權平均,那麼久需要多儲存一些額外的資訊,並且需要進行額外的加權計算。


實際案例



案例一


故障現場如下,某個應用的 SOA 服務抖動上升:

勇攀監控高峰 | EMonitor 之根因分析

直接點選根因分析,就可以分析到如下結果:

勇攀監控高峰 | EMonitor 之根因分析

AppId1 的 SOA 服務在某個機房下抖動了:
1、依賴的 AppId2 的 SOA 服務抖動。

  • 依賴的 AppId3 的 SOA 服務抖動。

  1. 依賴的 AppId5 的本地處理和 Redis 操作耗時抖動。

  2. 依賴的 AppId6 的本地處理和 Redis 操作耗時抖動。

  • 依賴的 AppId4 的本地處理和 Redis 操作耗時抖動。


這裡的本地處理包含獲取 Redis 連線物件 Jedis 的耗時,這一塊沒有耗時打點就導致劃分到本地處理上了,後續會進行最佳化。這裡沒有給出詳細的 Redis 叢集或者機器跟我們的實際情況有關,可以暫時忽略這一點。

點選上面的每個應用,下面的表格都會列出所點選應用的詳細故障資訊:
1、受影響的 SOA 服務有哪些,比如 AppId1 的 3 個 SOA 服務受到影響;
2、每個 SOA 服務抖動的根因,比如 AppId1 的 3 個 SOA 服務都受到 AppId2 的 1 個 SOA 服務的抖動影響;
3、表格中每一個連結都可以跳轉到對應的指標曲線監控皮膚上。

再比如點選 AppId4,顯示如下:

勇攀監控高峰 | EMonitor 之根因分析

AppId4 的 1 個 SOA 方法抖動:
1、該方法的本地處理抖動(實際是獲取 Redis 連線物件 Jedis 的耗時抖動);
2、該方法依賴的 Redis 操作抖動;
3、該方法丟擲 Redis 連線異常;

案例二


故障現場如下,某個應用的 SOA 服務抖動上升。

勇攀監控高峰 | EMonitor 之根因分析

點選根因分析,就可以幫你分析到如下結果:

勇攀監控高峰 | EMonitor 之根因分析

AppId1 的 SOA 服務在某個機房下抖動了:
1、依賴的 AppId2 的 SOA 服務抖動,依賴的 DB 服務抖動。
2、依賴的 AppId3 的 SOA 服務抖動,依賴的 AppId2 的 SOA 服務抖動,依賴的 DB 服務抖動。

點選 AppId2,可以看下詳細情況,如下所示:

勇攀監控高峰 | EMonitor 之根因分析

從表格中就可以看到,根因是 DB 的一臺例項抖動導致這個 dal group 所有操作抖動。

作者資訊:

李剛,網名乒乓狂魔,餓了麼監控組研發專家,餓了麼內部時序資料庫 LinDB 的專案負責人,餓了麼根因分析專案負責人,目前致力於監控的智慧分析領域以及下一代全景監控的體系化構建。

林濱(予譜),餓了麼監控組前端工程師,現負責一站式監控系統 EMonitor 的前端開發,旨在將繁雜的資料以高視覺化輸出。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69972138/viewspace-2705510/,如需轉載,請註明出處,否則將追究法律責任。

相關文章