本文根據匡淩軒老師在〖deeplus直播:虎牙APM可觀測平台建設實踐〗線上分享演講内容整理而成。(文末有回放的方式,不要錯過)
随着虎牙業務量的大規模增長,分布式應用服務架構日益複雜,排障定位變得越來越困難,原有傳統監控方式已無法跟上業務發展需要。虎牙建立設了一套APM平台,結合虎牙直播業務特性,也緊靠業界标準做了高度自研擴充,幫助研發和運維提高工作效率,保障線上應用服務穩定運作。
本次分享将通過以下幾個部分來介紹整體思路和實踐過程:
分享概要
一、項目背景 - 從當時痛點來思考關鍵切入點
二、方案實踐 - 采集、關聯、分析的設計思路和整體架構
三、效果展示 - 一站式排障,全鍊路根因定位
四、開放賦能 - Metric & Trace & Log對外賦能
五、Q&A
一、項目背景
1.當時痛點
虎牙當時各團隊的應用監控方案多樣,有自建應用接口日志采集監控,也有直接使用各類開源Trace系統,這樣就導緻跨團隊的鍊路無法互相打通,同時也缺乏統一的産品設計,極大地影響了整體排障效率。
2.切入點
從用戶端到後端分布式應用服務的全鍊路打通,提供透明零成本的接入方案快速覆寫業務,對Metric/Trace/Log監控資料進行整合并分析錯誤和異常,最終做到全鍊路根因定位。
3.目标
建設APM可觀測項目落地,根據錯誤的發現、定位和影響面分析等核心名額來指導方向和衡量效果,最終幫助使用者提高排障效率。
二、方案實踐
1.設計方案思考
- 資料采集:接入透明零成本是使用者願意接的關鍵
- 資料關聯:Metric & Trace & Log的可觀測關聯模型設計
- 全鍊路:用戶端 -> Nginx/信令 -> 分布式應用服務 -> 資料庫/緩存
- 根因定位:根據關聯模型資料的實時自動化分析來發現和定位問題
2.可觀測模型分析
根據應用服務處理請求的過程設計以下模型:
- Handle模型
描述該應用服務處理了什麼請求,調用什麼處理方法,使用什麼資源等,包括相關Metric/Span/Log資料采集,Trace上下文随請求處理線上程本地變量中進行透明傳遞。
- RPC模型
描述該應用服務有什麼RPC、Http、資料庫、緩存等請求調用,包括相關Metric/Span/Log資料采集,Trace上下文随請求頭在跨服務程序之間傳遞。
- 可觀測模型關聯
- 縱向:應用服務程序内、跨程序的請求調用鍊路關聯
- 橫向:隊列、線程池、連接配接池等資源資料和請求關聯
總結:設計包含從Handle和RPC資料采集,到縱向和橫向整體關聯的全鍊路可觀測模型,我們根據模型進一步設計了SDK和服務端的整體架構。
3.SDK架構介紹
- 零成本接入
- Java:位元組碼織入技術來自動識别多種架構并埋點
- C++:內建在Taf架構埋點
- 用戶端:內建在信令SDK埋點
- 基于業界标準
基于Opentracing标準選擇了Jaeger tracing的實作,通過自研設計和實作了Metric采集、聚合和關聯等邏輯。
- 分層和插件化
整體SDK架構分層清晰,基于Opentracing标準接口,相關底層和架構層都可以擴充實作一些個性功能,通過插件化設計來按需加載使用。
- 全量和采樣
Metric名額全量采集并聚合後上報。Trace Span明細需要采樣,支援遠端控制的動态前置采樣,以及有損後置采樣方案。
4.服務端架構介紹
- 采集、上報和控制
- Server App:Trace SDK在應用服務架構層進行自動化采集和上報
- Client App:內建在信令SDK層進行自動化采集和上報
- Sdk Control:sdk遠端控制服務,包括采樣政策、日志列印、功能啟停等控制
- Collector:資料接收服務,處理流控、驗證、清洗、轉換等邏輯
- 存儲、分析和告警
- Trace Sinker:spans明細資料的解析和存儲,按自研模型設定具體明細tags和logs
- Metric Sinker:名額資料解析和存儲,按自研模型設定相應的名額次元tags
- Meta Data Analyzer:分析對外連結路中繼資料,包含:請求uri、接口名、服務名、程序執行個體等
- Error Analyzer:分析時間線錯誤和異常來發現問題,再通過名額關聯和鍊路追蹤來定位根因
- 可視化和告警輸出
- Web Server:産品後端的API服務,負責資料檢索和業務邏輯處理
- Web/H5 App:産品前端的頁面展示、互動處理等可視化能力
- Wechat/SMS:企業微信、短信等方式的告警輸出
5.錯誤分析 - 應用性能根因定位
上圖右邊可以看到對請求處理流程的進一步解析,核心在于如何把請求處理追蹤和線程資源進行關聯,我們設計了反映服務處理能力的名額:線程負載率
上圖左邊的算法示例可以看到能發現應用服務GiftServer出現了線程負載高,應用性能不足問題,通過各請求的負載率分布來進一步分析,可以發現是由于/sendGift請求處理導緻,而它裡面的RPC請求/payMoney是根因問題。
效果示例:
6.錯誤分析 - 全鍊路根因定位
- Metric錯誤檢測
如上圖綠色框内是對應用服務内部Handle和RPC模型各類名額進行錯誤檢測:
Request Metrics // 請求名額
uri: /payMoney // 請求uri或方法名
totalCount: 1000 // 總請求數
errorCount: 200 // 錯誤請求數
latency avg: 2000ms // 請求平均耗時
errorRate: 20% // 請求錯誤率
...
發現請求錯誤率和平均耗時增加并在幾個周期内連續出現,按對應的告警分析規則就會判定為異常并産生實時告警發送給使用者。
- Metric關聯分析
如上圖名額的tag會記錄相應次元資訊來建立名額關聯,并通過的名額和鍊路關聯來進行錯誤根因分析:
service: GiftServer // 應用服務名
host: 192.168.1.1:8080 // 服務執行個體ip port
peerService: MoneyServer // rpc對端服務名
peerHost: 192.168.1.2:8081 // rpc對端執行個體ip port
type: rpc // 請求類型
service: MoneyServer // 應用服務名
host: 192.168.1.2:8081 // 服務執行個體ip port
peerService: Mysql // rpc對端服務名
peerHost: 192.168.1.3:3306 // rpc對端執行個體ip port
type: mysql // 請求類型
建立關聯:
請求: /sendGift 調用 /payMoney
服務: GiftServer 調用 MoneyServer
執行個體: 192.168.1.1:8080 調用192.168.1.2:8081
- Metric & Trace & Log
如上圖底部所示,通過從Metric宏觀錯誤告警到下鑽Trace/Log明細的關聯分析,建設實時全鍊路根因定位的平台能力。
三、效果展示
1.全鍊路根因分析
如上圖全鍊路拓撲圖展示錯誤根因節點和被影響鍊路節點,點選節點可以進一步按被調、主調和執行個體視圖來檢視宏觀名額情況,其中我們定位到是/hikari/getConnection耗時比較長導緻,我們還可以點選鍊路按鈕來進一步下鑽分析。
2.鍊路 - Trace明細分析
點選鍊路按鈕後打開Trace鍊路明細頁面,可以看到每次請求的明細鍊路情況,點選其中一條出錯的Trace,就可以看到如上圖所示的請求調用鍊視圖。可以快速分析定位到根因是擷取連結/hikari/getConnection的耗時長,導緻上遊的/getUser請求處理逾時。
3.名額 - 應用性能分析
點選名額按鈕後可以看具體的應用程序性能,通過右圖表請求處理的線程負載占比可以看到請求 /getUser 調用 /hikari/getConnection的線程負載率占比較高,左圖表線程狀态分析發現其根因是由于大多數工作線程阻塞在擷取連接配接的操作上。
4.名額 - 請求性能分析
來進一步看更多的請求性能名額,通過右圖表請求調用關系時延可以看到請求 /getUser 調用 /hikari/getConnection的平均耗時很大,左圖表可以分析具體的請求耗時區間分布占比情況,通過以上各種時序折線圖幫助我們快速分析具體的名額異常和變化趨勢。
5.告警分析 - 單節點聚集性問題
如上圖一站式排障流程,錯誤詳情頁面由上至下展示了錯誤基礎資訊、錯誤類型分布圖等,這裡可重點介紹一下中間的多節點調用聚合性根因定位:
鍊路 /getUser(sim-client) // URI接口(應用服務名)
-> /getUser(sim-first)
-> /getUser(sim-second:10.66.109.165:8001) // URI接口(應用服務名:執行個體ip:端口)
根因 Read timed out... // trace span log存儲的異常資訊,也可進一步看異常堆棧
主調影響範圍如下表:
主調服務:執行個體ip:端口 | 逾時率(%) | 請求數 | 平均耗時(ms) |
sim-client:10.116.18.223:8000 | 37.94 | 833 | 1070 |
sim-client:10.116.18.223:8000 | 33.52 | 880 | 1014 |
sim-client:10.116.18.223:8000 | 32.18 | 895 | 997 |
總結:從上面資訊可以直接看出多個節點主調發生逾時異常,是由于鍊路的根因節點sim-second:10.66.109.165:8001導緻,并能快速把範圍性影響的根因聚集到具體出錯節點上。該場景的核心就是把請求全鍊路 & 多節點聚集性進行關聯分析。
6.告警分析 - 應用性能瓶頸問題
如上圖一站式排障流程,錯誤詳情頁面由上至下展示了錯誤基礎資訊、線程負載率時序圖等,還是重點介紹中間的請求負載根因定位:
線程池名 tomcat.threadpool // 關聯目前服務架構的工作線程池
線程池快照 最大容量(200) 執行中(200) 阻塞中(190) // 關聯線程池資源名額
線程負載分布如下表:
總結:從上面資訊可以一直看出工作線程池已經跑滿,而且大部分線程執行中遇到了阻塞等待,從負載率具體請求分布來看,根因是由于/getUser 調用 /hikari/getConnection占比較高導緻。該場景的核心就是把請求處理 & 線程 & 連接配接進行關聯分析。
四、開放賦能
自從APM可觀測平台上線營運後,除了使用者對産品一些回報需求,也收到了很多對于平台能力開放的需求,是以我們建設了APM開放平台,用于開放能力賦能公司其他團隊,如上圖所示:
Case1:Metric時序資料
賦能AIOps異常檢測,提供各應用服務的請求時序資料給AI模型訓練,對部分個性服務和名額提供AI告警。
Case2:Trace明細資料
賦能自動化測試請求追蹤,自動化測試可以快速從用戶端到服務端全鍊路擷取錯誤根因,內建在自身系統邏輯中。
Case3:Trace包裹傳遞
賦能全鍊路請求染色,如對某個使用者進行染色後,會保障使用者uid随着trace上下文在整個請求鍊路進行透明傳遞,各應用服務都可通過trace sdk的api擷取使用者uid來列印日志或其他操作。
總結:APM可觀測平台這塊在虎牙統一可觀測規劃上屬于應用監控/鍊路追蹤,我們也在推進基礎設施監控、業務監控一起做一些整合,關鍵切入點還是在于各監控平台中繼資料的關聯分析,後續有機會再介紹這塊的思考和實踐。
Q&A
Q1:對應用有沒有性能影響?
A1:Metric資料對應用性能影響非常小,主要是在異步線程中做相關聚合運算,也就是說會把請求明細span按模型的名額定義來做聚合,生成請求量、耗時分布、錯誤量等名額,一個周期内10000次請求也隻會對名額值做改變,如:請求量: 10000次。但Trace span明細資料量是和請求量相關的,也就是采樣率100%的情況下目前節點會上報10000個span,在測試中發現對應用程序會有不少性能開銷,如果都上報的話對網絡流量和存儲也會開銷比較大,而大多數的明細span在實踐中價值不大,是以會采用一些前置采樣加有損後置采樣的政策來降低對整體性能和成本的影響。
Q2:鍊路span是怎麼跟那個時候的日志和名額關聯?
A2:SDK會根據Handle和RPC模型把Metric名額設定各種次元tag,這些tag會跟Trace span tag保持對應來關聯請求調用鍊名額和資源名額,而Trace span log會關聯儲存一些詳細異常日志和架構層日志。例如PPT分享的錯誤分析之應用性能根因定位和全鍊路根因定位裡有詳細介紹這塊的實作原理,進一步在PPT效果展示中也可以看到把Metric&Trace&Log進行關聯分析後的産品效果和應用場景。
Q3:開發人員自定義的日志可以采集嗎?
A3:Java主要使用基于slf4j的log4j或logback實作,我們對此在SDK開發了一個MDC(Mapped Diagnostic Context)擴充,在日志裡自動帶上traceId、spanId等資訊,而C++也把相應能力內建在架構日志元件中。這些自定義日志落盤後會被采集上報,在Log日志平台中可查詢展示,我們也跟日志平台在産品層做了打通關聯,會自動帶上trace id條件來查詢該請求鍊路上的所有自定義日志明細。
擷取本期PPT,請添加群秘微信号:dbachen
點選連結可回看本期直播:http://z-mz.cn/6FNsk
關于我們
dbaplus社群是圍繞Database、BigData、AIOps的企業級專業社群。資深大咖、技術幹貨,每天精品原創文章推送,每周線上技術分享,每月線下技術沙龍,每季度Gdevops&DAMS行業大會。
關注公衆号【dbaplus社群】,擷取更多原創技術文章和精選工具下載下傳