網易雲音樂全鏈路跟蹤系統實踐

本文講述了雲音樂全鏈路跟蹤系統的設計思想、實踐路線以及在技術選擇與功能迭代方面上思考總結。

爲什麼我們在三年前要立項做這個系統?當然是我們遇到了服務問題。當時最明顯的問題就是,隨着我們的服務化拆分越來越多,服務間調用關係越來越複雜,我們已經完全無法跟蹤系統的調用關係,某個鏈路出了問題,我們無法追溯,甚至那時候我們也沒有一個統一的日誌查詢平臺,我們需要不斷的登錄到不同的主機上去查詢日誌,可以想見當時的開發人員的生存環境是多麼的惡劣。所以,我們迫切的需要一個全鏈路跟蹤的系統,我們認爲有了全鏈路跟蹤,我們就能快速進行問題定位,異常排查,錯誤處理,性能優化了。

在系統建立之初,我們總體上有兩個大的方向,一個方向是全局視圖,即從整體上知道全局服務的依賴關係拓撲。第二個方向是能查詢任一請求的具體調用鏈路。

我總共分五章來闡述全鏈路跟蹤系統的整個發展歷程。每個章節包含了我們的目標及反思,以及我們對於爲什麼這麼做系統設計的原由。

第一章 調用棧與監控

首先第一章,調用棧與監控。

基於我們初期對鏈路系統的理解,調用棧和基礎監控指標是必須的,因爲只有有了調用棧關係,才能解決我們上下游調用無法串連跟蹤的問題。基礎監控是我們發現問題的底層保障。所以,我們就朝這個目標開幹了。

一、開源APM比較

在做之前,我們評估了當前世面上的大部分開源APM。這些系統大致情況如上,各有優劣,但後續我們還是走了了自研的道路。

爲什麼走上這條道路?這與我們的目標、我自身的認識、我的期望有莫大關係,同時,也與雲音樂的一貫風格有一點關係。

最後一欄Pylon,即雲音樂全鏈路監控系統,這個是我們目前已經選擇的方案及達到的能力,一併參與比較出來。

二、定義目標:低消耗、應用透明、實時監控、多維度分析

首先,我們做這個系統的底線是什麼?即鏈路系統消耗要低,不能對業務系統產生過多影響,鏈路系統是錦上添花的事情,絕不能成爲業務的包袱。在雲音樂當前的用戶體量下,trace日誌量一定是巨大的,所以,實時的異步上傳trace日誌一定會消耗大量網絡帶寬,同時,鏈路collector端的穩定性也會對業務系統產生一定影響。要保證輕量級,保證可控,那本地異步輸出日誌是最切實的保證。所以,我們就採用了寫本地日誌並由DS收集,最終寫入Kafka的方案來進行trace收集,從而摒棄掉了業務端直接上報的方案。當然,對於這種決策有重大影響的是另外一個系統的支持,即阿里的鷹眼。我們認爲雲音樂的體量已經不再適合直接上傳trace日誌了。

我們將所有的trace採集集成在中間件(包括RPC及各種存儲系統)這一層,來屏蔽掉對業務方的耦合。我們定義了我們自己的私有協議。當然,最近大部分開源APM系統都支持了opentracing協議。後續如果有必要,我們也會考慮支持上。支持的好處在於,我們可以使用開源的採集客戶端來豐富化、多樣化我們對各種組件的trace支持,同時使用自己的後端處理系統來提供強大的數據分析能力。

當然,我們基於應用名、鏈路名、主機IP等多維數據查詢需求,使我們選擇了ES作爲底層存儲系統。爲了獲得實時的數據聚合能力,我們首次提出使用Flink來解決流式處理問題。

這樣,所有組件都齊備了,現在就需要考慮如何設計我們的系統了。

三、系統架構

這就是我們的系統架構,一看就能明白,此處不再詳談。

四、維度分析

我們到底如何開始我們的設計呢?

想象一下我們的用戶,他該如何開始我們的系統?他應該從最宏觀的方向入手,例如,他應該知道某個應用需要關注,因爲這個應用在某段時間不健康了。然後,深入到這個應用內部,他發現了哪個RPC/API有問題,接着,他可以發現是某些主機的問題,也可以發現是所有主機都存在某個問題。最終,他需要確切知道到底哪兒引起了問題,這時候,他要找到一系列請求,來查看問題出現在哪個調用棧上。

於是,我們提取了整個流程,來繪製我們的數據視圖。主要包括:應用->鏈路->主機->請求。這是一個層層遞進,由表及裏的過程。

五、時間粒度

當然,在數據的粒度方面,我們定義了一些基礎粒度,如5s、1m、5min、1h,基於這些基礎粒度,我們可以實現任意時間區間,任意粒度切換。怎麼說了,選擇一個時間區間,我們自行判定與組合該區間內包含的基礎粒度指標,達到隨意選擇的目標。同時,我們多粒度的設計也能高效查詢返回。例如查詢一週的數據,我們可以使用1h的粒度作爲基礎粒度進行聚合返回。查詢5h30min的區間大小我們可以組合若干1h粒度及若干1min鍾粒度進行聚合。這樣的設計對用戶查詢是非常友好的。

其次,由於是流式處理,多粒度的聚合即減少了採集數據延遲帶來的整體數據量的誤差,同時也解決了查詢實時性的問題。

各維度,各粒度的基礎監控

基於traceId的鏈路查詢

如上圖所示,我們在第一章節就完成了我們的基礎目標,達到了基礎監控與調用棧查詢的能力。但是,在使用過程中發現,達到這一步還很不夠,因爲雖然有了基礎監控,但是在某一異常時間點關聯的異常請求太多了,並且異常服務也非常多,隨機選擇一個異常請求是完全沒辦法判定root cause的,因爲很多異常請求都是由於線程池滿導致了timeout錯誤,但我們卻無法從茫茫異常請求中找到導致線程池滿的根源。

於是,我們需要對服務進行全量梳理,我們需要發現內部的關聯關係,我們認爲,有了一個全局的異常拓撲圖,我們就能從拓撲圖上找到異常的root cause應用了。

第二章 服務梳理 指標強化

現在進入我們的第二章。服務梳理,指標強化。

我們有了那麼多監控數據,有了那麼多具體請求調用數據,我們發現用戶使用成本很高,甚至無從下手,那爲什麼會出現這種情況?這是我們設計之初忽略掉的問題,即線上服務太多了,服務之間的依賴太複雜,異常的發生是相互傳遞的,當某個服務出現異常時,它的所有依賴服務也會出現問題。我們抓取到的任何一個異常請求,都可能由於上層依賴的服務同時異常而請求中止掉,從而我們無法真正找到底層直接異常服務,即root cause服務。

那該如何解決這個問題?必須全面梳理服務關係及鏈路關係,必須強化各項指標的監測。

這一階段,我們需要整理服務的調用關係,需要對性能優化進行指導,業務最關心的異常需要直接展現,同時提供全環境支持。

一、服務梳理

具體來說,服務梳理,首先梳理應用的直接依賴應用,應用的調用關係,同時,需要梳理應用與其他應用產生了哪些鏈路調用及依賴。

鏈路梳理,即梳理鏈路間的調用關係及依賴關係,鏈路的調用拓撲及鏈路強弱依賴等。

有了這些關係數據,我們現在終於知道每個服務、鏈路它所處的位置、它的拓撲關係,可以完整繪製出所有服務拓撲大盤了。全局服務中任一服務出現了問題,我們基於拓撲大盤,就能快速定位到最底層的root cause應用及root cause鏈路了。

這在故障定位方面前進了一大步。我們可以看一下具體異常時後的拓撲表現:

全局異常拓撲、應用依賴關係、應用鏈路關係

如上圖所示,我們在此階段可視化了服務間的調用依賴關係,能夠快速清晰的展現應用與鏈路間雜亂的網狀結構。

鏈路調用關係(統計視圖)

二、統計分析

當然,我們也提供了豐富的統計分析數據。這些數據有一些是基礎性的,如總量、均值、區間振幅;有一些是高級的,如直方圖、調和平均、離散度、百分位統計等。

  • 調和平均能減弱個別極大值的影響,獲得更加準確的平均響應指標;

  • 直方圖更加豐富的描述了響應的分佈區間(可基於響應區間查找對應請求);

  • 散點圖更快的發現全局鏈路、主機、請求中需要調優的信息(越離散穩定性越差);

  • 百分位統計能夠描述極端信息(落在99%百分位區間的數據是極端數據,或異常點);

  • 振幅描述了響應時間的極小極大區間。

這些數據能夠全面而完整的呈現出服務在某一階段的質量狀態。

基礎統計指標

離散度、響應直方圖、百分位統計

三、服務關係

然後,我們打通了網易內部及雲音樂體系中的其他系統,包括提供基礎主機監控的哨兵,依賴cmdb業務分組建立了業務視圖,打通了配置中心獲取服務中間件組件,關聯了RPC元數據來提供每個請求的RPC更多內部信息。每一個請求與日誌關聯,同時,我們也提供出了SLO與GoTest的外部分析通道。有了這一些組件的數據關聯,我們基本建立了對所有系統的分析循環。

四、功能特性

基於自身的大數據,及外部系統的數據依賴,我們完成了許多的基礎功能建設。包括業務分組視圖、全局搜索、慢響應分析、健康色譜、集羣視圖、異常鏈路與日誌、組件配置等。這些功能特性極大的豐富了數據的使用場景,提高了整個全鏈路系統的問題分析能力。

  • 分組:將應用按業務組層級進行展示,該分組數據來源於cmdb;

  • 全局搜索:提供了基於前綴匹配的全局關鍵詞搜索,可支持應用名,鏈路名,主機IP,traceId搜索

  • 慢響應:展示指定時間範圍內應用/鏈路的最慢響應請求(最多200個);

  • 色譜:默認展示最近5h的應用/鏈路健康診斷情況,健康程度用顏色塊展示,藍色表示健康,紅色表示不健康。

各種分析能力分模塊集成在應用分析、鏈路分析、主機分析、服務分析等獨立分析頁上,以下展示應用分析頁:

應用分析

五、全環境

全環境最大化輸出了系統對業務的使用場景與能力,完整覆蓋了開發使用的各個環境。

第三章 全局質量 根源定位

有了這些豐富的指標,有了對服務的梳理,我們也能定位到root cause應用了,但在實踐中發現,這還很不夠。

1、由於我們缺乏中間件數據(redis, mysql, memcache等)採集,從而導致我們喪失了更具體的異常定位能力。我們只知道某個應用出了問題,但是不知道應用出了什麼問題。

2、實踐中發現線上環境遠比想象的更復雜。既使在整體服務質量較高的情況下,線上幾百個服務的異常及超時都在隨時發生。整個全局異常拓撲都呈現出大片紅彤彤的景象。按照這樣的拓撲圖,既使真正異常發生時,干擾的異常也足以淹沒掉真正的root cause應用,更別提更細緻的定位了。

一、目標:自動化服務診斷、高效的異常定位

所以,在第三章,我們的總體目標即爲自動化服務診斷,能夠發現服務確實存在某些問題;及在此基礎上達到異常定位的能力。

二、服務診斷

我們的服務診斷,即是分類服務中存在的問題。首先,我們需要把所有服務異常按嚴重程度進行劃分,於是我們建立起了服務的健康質量分類,包含:

  • 無異常/超時的健康服務;

  • 少異常/超時的亞健康服務;

  • 超過95%異常統計區間的告警服務;

  • 超過99%異常統計區間的高危險服務。

前兩類服務都是不需要作爲關注目標的服務,基於此分類,基本可以過濾掉絕大部分有異常但不影響服務質量的應用/鏈路了。後兩類服務是需要進行關注的服務,因爲他們的異常量已經達到歷史統計的極端區間,雖然並不表明他們一定存在某些問題,但也需引起開發者的注意。

不僅如此,在線上爆發大規模異常時,告警與危險類別即可作爲當前故障對全局影響程度的可靠指標,因爲這兩個類別已經非常明確且高效的告訴了開發者,這些服務已經深受故障影響,異常/超時達到甚至超過了歷史統計極值。

在服務診斷中,我們還有一個指標,即抖動。抖動是通過對響應時間的正態分佈統計中劃分的置信區間,來判定當前響應是否存在毛刺。我們通過對抖動次數的長期統計,建立起對統計值的百分位等級劃分,來判定服務的不穩定程度。通常,我們將達到99%百分位的抖動劃定位高危險抖動,並由此推斷服務存在極大的問題需要進行排查。

服務健康等級、鏈路健康等級、抖動識別

三、問題定位

那我們有了服務診斷,該如何定位到具體的問題了?

這是一個很難的問題,需要有大量的數據,這些數據需要包含所有上下游的所有信息;同時,對所有數據進行分析篩選過濾,來發現真正引發問題的root cause。

雖然哨兵包含了非常豐富的指標,但由於我們當前無法對哨兵數據進行有效同步分析,於是我們選擇了另外一個方向,即基於服務異常日誌來進行全量分析。

  • 首先,異常日誌是全量的,不存在採樣率一說;

  • 其次,異常日誌是排查與定位問題的通用方法。只要我們能夠非常高效而準確的對異常日誌進行整理,那找到問題的root cause就是相對簡單的事情了。

所以:

  • 第一步,我們需要對所有異常日誌進行分類提取。這一步主要過濾所有異常日誌中包含的變量信息;

  • 第二步,變量信息被佔位符替換後,我們着手建立所有異常的分類。即包含相同描述與調用棧的異常歸爲同一個類別;

  • 第三步,我們建立一套標籤規則,所有符合某個規則的異常分類會打上相應標籤;

  • 第四步,我們針對標籤及異常產生的頻率建立一個評分機制;

  • 最後,我們將所有異常按評分進行排序。

這樣,當異常發生時,在大量繁雜的異常中,我們基於這套標籤及評分機制,能夠較快較好的獲取問題定位的快速判定。

當然,我們還對非常重要的異常進行了特異化的信息提取,如RPC超時異常。我們提取了其中包含的RPC key信息及IP, Port,並建立了對該數據的實時統計。這樣,我們基於此數據能非常明確的知道服務的質量情況,以及哪些主機存在問題。當然,現在的侷限性在於,這個機制對應用異常非常準確,但對中間件異常,無法獲取到有效的主機信息(因爲當前缺少中間件異常日誌數據)。

基於標籤化的異常分類日誌排序展示

異常日誌中提取的RPC信息

四、全局診斷

現在,我們可以建立起全局的診斷視圖了。包括全局的健康指標,流控降級應用、線程池異常的服務、優化的異常拓撲,同時包含同比環比等各項數據。其中,線程池、流控降級數據基於日誌標籤進行獲取;高危抖動來源於抖動分級;異常拓撲進行了優化,只展現告警及危險級拓撲關係,標籤雲來源於全局日誌標籤,同環比、趨勢圖皆來自於實時流統計監控指標,服務分類來源於整體應用的服務分級。

綜合這些數據,我們既能判定異常,又能判定影響範圍,既能獲知故障程度,又能排查故障來源(如果發生中間件組件異常,只能通過異常分類進行排查,無法通過RPC信息獲取於具體的主機,除非中間件異常信息包含了主機信息)。於是,我們構建起了完整而又實時的服務健康圖譜。

全局及應用異常依斷、異常拓撲優化

如上,優化過的異常拓撲圖明顯比原始的異常拓撲清晰很多,主要原因在於優化後過濾掉了很多幹擾的異常數據,突出了與當前故障更相關的異常。

第四章 平臺 業務 數據

一、目標:多平臺全面整合、多業務數據共享、基礎設施、生態閉環

我們的目標是,與其他平臺全面整合,推動數據與業務共享,建立監控生態閉環。

助力業務,主要分爲兩個部分,第一,基於抖動檢測的實時報警;第二,基於異常/性能分析的分類報表。

  • 基於當前的抖動檢測,我們主動識別抖動週期性,對於非週期性抖動進行實時抖動通知。當前的抖動主要通過系統判定,也輔助支持業務閾值設置;

  • 對於日誌異常,我們在異常類別的基礎上將統計數據推送到質量可視化平臺,在質量可視化平臺按業務組展現各業務的報表大盤,最終由業務方通過該入口來推進異常整改,性能調優。

當前我們大力推進全鏈路系統與日誌,SLO,網關、存儲,RPC,靜態化等各項服務打通,做到數據的高度融合。同時,我們已經完成了雲音樂內部其他服務的數據輸出,在質量、效率、穩定性、性能方向建立了強大的能力圖譜。全鏈路跟蹤系統已經從單一的服務系統轉變爲雲音樂內部基礎設施系統,從面向業務開發擴展到面向服務,達到雲音樂內部整體生態閉環的目標。

二、數據量級

  • 當前接入的400+應用,6000+API,基本囊括了主要的應用服務及對外接口;

  • 每天寫入94億數據量,這個量級是網易內其他產品系無法比擬的;

  • 每天的數據處理QPS高達170K,數據存儲量也高達4.5T,說明它有強勁的數據處理與分析能力。

以上還在在當前採樣率很低的情況下的數據(當前採樣率不是固定的,是以要採集到多個請求來計算每個API需要配置多大采樣率,默認採樣率是千分之一)。

所以,它的價值,在20年以及在未來,一定會不斷強化與滲透到雲音樂系統建設的各個方面。

第五章 發展與未來

當前的目標是提供更加智能化的問題分析定位能力,補全我們在存儲監控上的短板;同時trace客戶端支持雲音樂全量組件,最後能在業界獲取一定的技術傳播。

在存儲方面,我們基於OWL基礎數據建設存儲系統的基礎架構可視化,建立所有存儲的應用依賴關聯,同時獲取各存儲的性能監控實時指標,最後建立存儲組件的服務質量量化標準。

當前trace客戶端主要基於RPC及mylife公共組件。對於異步線程池,HTTP、HBase等都需要業務調用trace API打點,耦合性較強。同時,由於使用私有協議,無法與業界通用的標準協議打通,後續考慮支持標準的openTracing協義,同時對於各組件模塊,業務方可以使用業界最全的pinpoint trace客戶端進行打點採集。

最後,我們要進行智能化平臺建設。基於深度學習與神經網絡的預學習建模,來獲得更高的準確性分析,包括異常分類問題,時間序列預測問題等,來解決流處理實時性及數據完整性的問題;同時,基於預建模型,我們能更方便的對數據進行有效性判斷,對於非重要數據,直接不進行存儲來節省存儲空間。

作者簡介

郭元華,網易雲音樂技術中心公共技術組技術負責人,java技術專家。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章