全鏈路根因定位,虎牙APM可觀測(cè)平臺(tái)建設(shè)實(shí)踐
隨著虎牙業(yè)務(wù)量的大規(guī)模增長(zhǎng),分布式應(yīng)用服務(wù)架構(gòu)日益復(fù)雜,排障定位變得越來(lái)越困難,原有傳統(tǒng)監(jiān)控方式已無(wú)法跟上業(yè)務(wù)發(fā)展需要?;⒀佬陆ㄔO(shè)了一套APM平臺(tái),結(jié)合虎牙直播業(yè)務(wù)特性,也緊靠業(yè)界標(biāo)準(zhǔn)做了高度自研擴(kuò)展,幫助研發(fā)和運(yùn)維提高工作效率,保障線上應(yīng)用服務(wù)穩(wěn)定運(yùn)行。
本次分享將通過(guò)以下幾個(gè)部分來(lái)介紹整體思路和實(shí)踐過(guò)程:
一、項(xiàng)目背景
圖片
1.當(dāng)時(shí)痛點(diǎn)
虎牙當(dāng)時(shí)各團(tuán)隊(duì)的應(yīng)用監(jiān)控方案多樣,有自建應(yīng)用接口日志采集監(jiān)控,也有直接使用各類開(kāi)源Trace系統(tǒng),這樣就導(dǎo)致跨團(tuán)隊(duì)的鏈路無(wú)法相互打通,同時(shí)也缺乏統(tǒng)一的產(chǎn)品設(shè)計(jì),極大地影響了整體排障效率。
2.切入點(diǎn)
從客戶端到后端分布式應(yīng)用服務(wù)的全鏈路打通,提供透明零成本的接入方案快速覆蓋業(yè)務(wù),對(duì)Metric/Trace/Log監(jiān)控?cái)?shù)據(jù)進(jìn)行整合并分析錯(cuò)誤和異常,最終做到全鏈路根因定位。
3.目標(biāo)
建設(shè)APM可觀測(cè)項(xiàng)目落地,根據(jù)錯(cuò)誤的發(fā)現(xiàn)、定位和影響面分析等核心指標(biāo)來(lái)指導(dǎo)方向和衡量效果,最終幫助用戶提高排障效率。
二、方案實(shí)踐
1.設(shè)計(jì)方案思考
圖片
數(shù)據(jù)采集:接入透明零成本是用戶愿意接的關(guān)鍵
數(shù)據(jù)關(guān)聯(lián):Metric & Trace & Log的可觀測(cè)關(guān)聯(lián)模型設(shè)計(jì)
全鏈路:客戶端 -> Nginx/信令 -> 分布式應(yīng)用服務(wù) -> 數(shù)據(jù)庫(kù)/緩存
根因定位:根據(jù)關(guān)聯(lián)模型數(shù)據(jù)的實(shí)時(shí)自動(dòng)化分析來(lái)發(fā)現(xiàn)和定位問(wèn)題
2.可觀測(cè)模型分析
圖片
根據(jù)應(yīng)用服務(wù)處理請(qǐng)求的過(guò)程設(shè)計(jì)以下模型:
- Handle模型
描述該應(yīng)用服務(wù)處理了什么請(qǐng)求,調(diào)用什么處理方法,使用什么資源等,包括相關(guān)Metric/Span/Log數(shù)據(jù)采集,Trace上下文隨請(qǐng)求處理在線程本地變量中進(jìn)行透明傳遞。
- RPC模型
描述該應(yīng)用服務(wù)有什么RPC、Http、數(shù)據(jù)庫(kù)、緩存等請(qǐng)求調(diào)用,包括相關(guān)Metric/Span/Log數(shù)據(jù)采集,Trace上下文隨請(qǐng)求頭在跨服務(wù)進(jìn)程之間傳遞。
- 可觀測(cè)模型關(guān)聯(lián)
- 縱向:應(yīng)用服務(wù)進(jìn)程內(nèi)、跨進(jìn)程的請(qǐng)求調(diào)用鏈路關(guān)聯(lián)
- 橫向:隊(duì)列、線程池、連接池等資源數(shù)據(jù)和請(qǐng)求關(guān)聯(lián)
總結(jié):設(shè)計(jì)包含從Handle和RPC數(shù)據(jù)采集,到縱向和橫向整體關(guān)聯(lián)的全鏈路可觀測(cè)模型,我們根據(jù)模型進(jìn)一步設(shè)計(jì)了SDK和服務(wù)端的整體架構(gòu)。
3.SDK架構(gòu)介紹
圖片
- 零成本接入
- Java:字節(jié)碼織入技術(shù)來(lái)自動(dòng)識(shí)別多種框架并埋點(diǎn)
- C++:集成在Taf框架埋點(diǎn)
- 客戶端:集成在信令SDK埋點(diǎn)
- 基于業(yè)界標(biāo)準(zhǔn)
基于Opentracing標(biāo)準(zhǔn)選擇了Jaeger tracing的實(shí)現(xiàn),通過(guò)自研設(shè)計(jì)和實(shí)現(xiàn)了Metric采集、聚合和關(guān)聯(lián)等邏輯。
- 分層和插件化
整體SDK架構(gòu)分層清晰,基于Opentracing標(biāo)準(zhǔn)接口,相關(guān)底層和框架層都可以擴(kuò)展實(shí)現(xiàn)一些個(gè)性功能,通過(guò)插件化設(shè)計(jì)來(lái)按需加載使用。
- 全量和采樣
Metric指標(biāo)全量采集并聚合后上報(bào)。Trace Span明細(xì)需要采樣,支持遠(yuǎn)程控制的動(dòng)態(tài)前置采樣,以及有損后置采樣方案。
4.服務(wù)端架構(gòu)介紹
圖片
采集、上報(bào)和控制
- Server App:Trace SDK在應(yīng)用服務(wù)框架層進(jìn)行自動(dòng)化采集和上報(bào)
- Client App:集成在信令SDK層進(jìn)行自動(dòng)化采集和上報(bào)
- Sdk Control:sdk遠(yuǎn)程控制服務(wù),包括采樣策略、日志打印、功能啟停等控制
- Collector:數(shù)據(jù)接收服務(wù),處理流控、驗(yàn)證、清洗、轉(zhuǎn)換等邏輯
存儲(chǔ)、分析和告警
- Trace Sinker:spans明細(xì)數(shù)據(jù)的解析和存儲(chǔ),按自研模型設(shè)置具體明細(xì)tags和logs
- Metric Sinker:指標(biāo)數(shù)據(jù)解析和存儲(chǔ),按自研模型設(shè)置相應(yīng)的指標(biāo)維度tags
- Meta Data Analyzer:分析出鏈路元數(shù)據(jù),包含:請(qǐng)求uri、接口名、服務(wù)名、進(jìn)程實(shí)例等
- Error Analyzer:分析時(shí)間線錯(cuò)誤和異常來(lái)發(fā)現(xiàn)問(wèn)題,再通過(guò)指標(biāo)關(guān)聯(lián)和鏈路追蹤來(lái)定位根因
可視化和告警輸出
- Web Server:產(chǎn)品后端的API服務(wù),負(fù)責(zé)數(shù)據(jù)檢索和業(yè)務(wù)邏輯處理
- Web/H5 App:產(chǎn)品前端的頁(yè)面展示、交互處理等可視化能力
- Wechat/SMS:企業(yè)微信、短信等方式的告警輸出
5.錯(cuò)誤分析 - 應(yīng)用性能根因定位
圖片
上圖右邊可以看到對(duì)請(qǐng)求處理流程的進(jìn)一步解析,核心在于如何把請(qǐng)求處理追蹤和線程資源進(jìn)行關(guān)聯(lián),我們?cè)O(shè)計(jì)了反映服務(wù)處理能力的指標(biāo):線程負(fù)載率
上圖左邊的算法示例可以看到能發(fā)現(xiàn)應(yīng)用服務(wù)GiftServer出現(xiàn)了線程負(fù)載高,應(yīng)用性能不足問(wèn)題,通過(guò)各請(qǐng)求的負(fù)載率分布來(lái)進(jìn)一步分析,可以發(fā)現(xiàn)是由于/sendGift請(qǐng)求處理導(dǎo)致,而它里面的RPC請(qǐng)求/payMoney是根因問(wèn)題。
效果示例:
圖片
6.錯(cuò)誤分析 - 全鏈路根因定位
圖片
- Metric錯(cuò)誤檢測(cè)
如上圖綠色框內(nèi)是對(duì)應(yīng)用服務(wù)內(nèi)部Handle和RPC模型各類指標(biāo)進(jìn)行錯(cuò)誤檢測(cè):
Request Metrics // 請(qǐng)求指標(biāo)
uri: /payMoney // 請(qǐng)求uri或方法名
totalCount: 1000 // 總請(qǐng)求數(shù)
errorCount: 200 // 錯(cuò)誤請(qǐng)求數(shù)
latency avg: 2000ms // 請(qǐng)求平均耗時(shí)
errorRate: 20% // 請(qǐng)求錯(cuò)誤率
...
發(fā)現(xiàn)請(qǐng)求錯(cuò)誤率和平均耗時(shí)增加并在幾個(gè)周期內(nèi)連續(xù)出現(xiàn),按對(duì)應(yīng)的告警分析規(guī)則就會(huì)判定為異常并產(chǎn)生實(shí)時(shí)告警發(fā)送給用戶。
- Metric關(guān)聯(lián)分析
如上圖指標(biāo)的tag會(huì)記錄相應(yīng)維度信息來(lái)建立指標(biāo)關(guān)聯(lián),并通過(guò)的指標(biāo)和鏈路關(guān)聯(lián)來(lái)進(jìn)行錯(cuò)誤根因分析:
service: GiftServer // 應(yīng)用服務(wù)名
host: 192.168.1.1:8080 // 服務(wù)實(shí)例ip port
peerService: MoneyServer // rpc對(duì)端服務(wù)名
peerHost: 192.168.1.2:8081 // rpc對(duì)端實(shí)例ip port
type: rpc // 請(qǐng)求類型
service: MoneyServer // 應(yīng)用服務(wù)名
host: 192.168.1.2:8081 // 服務(wù)實(shí)例ip port
peerService: Mysql // rpc對(duì)端服務(wù)名
peerHost: 192.168.1.3:3306 // rpc對(duì)端實(shí)例ip port
type: mysql // 請(qǐng)求類型
建立關(guān)聯(lián):
請(qǐng)求: /sendGift 調(diào)用 /payMoney
服務(wù): GiftServer 調(diào)用 MoneyServer
實(shí)例: 192.168.1.1:8080 調(diào)用192.168.1.2:8081
- Metric & Trace & Log
如上圖底部所示,通過(guò)從Metric宏觀錯(cuò)誤告警到下鉆Trace/Log明細(xì)的關(guān)聯(lián)分析,建設(shè)實(shí)時(shí)全鏈路根因定位的平臺(tái)能力。
三、效果展示
1.全鏈路根因分析
圖片
如上圖全鏈路拓?fù)鋱D展示錯(cuò)誤根因節(jié)點(diǎn)和被影響鏈路節(jié)點(diǎn),點(diǎn)擊節(jié)點(diǎn)可以進(jìn)一步按被調(diào)、主調(diào)和實(shí)例視圖來(lái)查看宏觀指標(biāo)情況,其中我們定位到是/hikari/getConnection耗時(shí)比較長(zhǎng)導(dǎo)致,我們還可以點(diǎn)擊鏈路按鈕來(lái)進(jìn)一步下鉆分析。
2.鏈路 - Trace明細(xì)分析
點(diǎn)擊鏈路按鈕后打開(kāi)Trace鏈路明細(xì)頁(yè)面,可以看到每次請(qǐng)求的明細(xì)鏈路情況,點(diǎn)擊其中一條出錯(cuò)的Trace,就可以看到如上圖所示的請(qǐng)求調(diào)用鏈視圖??梢钥焖俜治龆ㄎ坏礁蚴谦@取鏈接/hikari/getConnection的耗時(shí)長(zhǎng),導(dǎo)致上游的/getUser請(qǐng)求處理超時(shí)。
3.指標(biāo) - 應(yīng)用性能分析
圖片
點(diǎn)擊指標(biāo)按鈕后可以看具體的應(yīng)用進(jìn)程性能,通過(guò)右圖表請(qǐng)求處理的線程負(fù)載占比可以看到請(qǐng)求 /getUser 調(diào)用 /hikari/getConnection的線程負(fù)載率占比較高,左圖表線程狀態(tài)分析發(fā)現(xiàn)其根因是由于大多數(shù)工作線程阻塞在獲取連接的操作上。
4.指標(biāo) - 請(qǐng)求性能分析
圖片
來(lái)進(jìn)一步看更多的請(qǐng)求性能指標(biāo),通過(guò)右圖表請(qǐng)求調(diào)用關(guān)系時(shí)延可以看到請(qǐng)求 /getUser 調(diào)用 /hikari/getConnection的平均耗時(shí)很大,左圖表可以分析具體的請(qǐng)求耗時(shí)區(qū)間分布占比情況,通過(guò)以上各種時(shí)序折線圖幫助我們快速分析具體的指標(biāo)異常和變化趨勢(shì)。
5.告警分析 - 單節(jié)點(diǎn)聚集性問(wèn)題
圖片
如上圖一站式排障流程,錯(cuò)誤詳情頁(yè)面由上至下展示了錯(cuò)誤基礎(chǔ)信息、錯(cuò)誤類型分布圖等,這里可重點(diǎn)介紹一下中間的多節(jié)點(diǎn)調(diào)用聚合性根因定位:
鏈路 /getUser(sim-client) // URI接口(應(yīng)用服務(wù)名)
-> /getUser(sim-first)
-> /getUser(sim-second:10.66.109.165:8001) // URI接口(應(yīng)用服務(wù)名:實(shí)例ip:端口)
根因 Read timed out... // trace span log存儲(chǔ)的異常信息,也可進(jìn)一步看異常堆棧
主調(diào)影響范圍如下表:
主調(diào)服務(wù):實(shí)例ip:端口 | 超時(shí)率(%) | 請(qǐng)求數(shù) | 平均耗時(shí)(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 |
總結(jié):從上面信息可以直接看出多個(gè)節(jié)點(diǎn)主調(diào)發(fā)生超時(shí)異常,是由于鏈路的根因節(jié)點(diǎn)sim-second:10.66.109.165:8001導(dǎo)致,并能快速把范圍性影響的根因聚集到具體出錯(cuò)節(jié)點(diǎn)上。該場(chǎng)景的核心就是把請(qǐng)求全鏈路 & 多節(jié)點(diǎn)聚集性進(jìn)行關(guān)聯(lián)分析。
6.告警分析 - 應(yīng)用性能瓶頸問(wèn)題
如上圖一站式排障流程,錯(cuò)誤詳情頁(yè)面由上至下展示了錯(cuò)誤基礎(chǔ)信息、線程負(fù)載率時(shí)序圖等,還是重點(diǎn)介紹中間的請(qǐng)求負(fù)載根因定位:
線程池名 tomcat.threadpool // 關(guān)聯(lián)當(dāng)前服務(wù)框架的工作線程池
線程池快照 最大容量(200) 執(zhí)行中(200) 阻塞中(190) // 關(guān)聯(lián)線程池資源指標(biāo)
線程負(fù)載分布如下表:
請(qǐng)求URI | 負(fù)載率(%) | 請(qǐng)求數(shù) | 平均耗時(shí)(ms) |
/getUser | 98.82 | 606 | 17417 |
/getUser 調(diào)用 /hikari/getConnection | 93.24 | 610 | 16632 |
/getUser 調(diào)用 /hikari/xiwi/SELECT | 5 | 606 | 983 |
總結(jié):從上面信息可以一直看出工作線程池已經(jīng)跑滿,而且大部分線程執(zhí)行中遇到了阻塞等待,從負(fù)載率具體請(qǐng)求分布來(lái)看,根因是由于/getUser 調(diào)用 /hikari/getConnection占比較高導(dǎo)致。該場(chǎng)景的核心就是把請(qǐng)求處理 & 線程 & 連接進(jìn)行關(guān)聯(lián)分析。
四、開(kāi)放賦能
圖片
自從APM可觀測(cè)平臺(tái)上線運(yùn)營(yíng)后,除了用戶對(duì)產(chǎn)品一些反饋需求,也收到了很多對(duì)于平臺(tái)能力開(kāi)放的需求,因此我們建設(shè)了APM開(kāi)放平臺(tái),用于開(kāi)放能力賦能公司其他團(tuán)隊(duì),如上圖所示:
Case1:Metric時(shí)序數(shù)據(jù)
賦能AIOps異常檢測(cè),提供各應(yīng)用服務(wù)的請(qǐng)求時(shí)序數(shù)據(jù)給AI模型訓(xùn)練,對(duì)部分個(gè)性服務(wù)和指標(biāo)提供AI告警。
Case2:Trace明細(xì)數(shù)據(jù)
賦能自動(dòng)化測(cè)試請(qǐng)求追蹤,自動(dòng)化測(cè)試可以快速?gòu)目蛻舳说椒?wù)端全鏈路獲取錯(cuò)誤根因,集成在自身系統(tǒng)邏輯中。
Case3:Trace包裹傳遞
賦能全鏈路請(qǐng)求染色,如對(duì)某個(gè)用戶進(jìn)行染色后,會(huì)保障用戶uid隨著trace上下文在整個(gè)請(qǐng)求鏈路進(jìn)行透明傳遞,各應(yīng)用服務(wù)都可通過(guò)trace sdk的api獲取用戶uid來(lái)打印日志或其他操作。
總結(jié):APM可觀測(cè)平臺(tái)這塊在虎牙統(tǒng)一可觀測(cè)規(guī)劃上屬于應(yīng)用監(jiān)控/鏈路追蹤,我們也在推進(jìn)基礎(chǔ)設(shè)施監(jiān)控、業(yè)務(wù)監(jiān)控一起做一些整合,關(guān)鍵切入點(diǎn)還是在于各監(jiān)控平臺(tái)元數(shù)據(jù)的關(guān)聯(lián)分析,后續(xù)有機(jī)會(huì)再介紹這塊的思考和實(shí)踐。
Q&A
Q1:對(duì)應(yīng)用有沒(méi)有性能影響?
A1:Metric數(shù)據(jù)對(duì)應(yīng)用性能影響非常小,主要是在異步線程中做相關(guān)聚合運(yùn)算,也就是說(shuō)會(huì)把請(qǐng)求明細(xì)span按模型的指標(biāo)定義來(lái)做聚合,生成請(qǐng)求量、耗時(shí)分布、錯(cuò)誤量等指標(biāo),一個(gè)周期內(nèi)10000次請(qǐng)求也只會(huì)對(duì)指標(biāo)值做改變,如:請(qǐng)求量: 10000次。但Trace span明細(xì)數(shù)據(jù)量是和請(qǐng)求量相關(guān)的,也就是采樣率100%的情況下當(dāng)前節(jié)點(diǎn)會(huì)上報(bào)10000個(gè)span,在測(cè)試中發(fā)現(xiàn)對(duì)應(yīng)用進(jìn)程會(huì)有不少性能開(kāi)銷,如果都上報(bào)的話對(duì)網(wǎng)絡(luò)流量和存儲(chǔ)也會(huì)開(kāi)銷比較大,而大多數(shù)的明細(xì)span在實(shí)踐中價(jià)值不大,所以會(huì)采用一些前置采樣加有損后置采樣的策略來(lái)降低對(duì)整體性能和成本的影響。
Q2:鏈路span是怎么跟那個(gè)時(shí)候的日志和指標(biāo)關(guān)聯(lián)?
A2:SDK會(huì)根據(jù)Handle和RPC模型把Metric指標(biāo)設(shè)置各種維度tag,這些tag會(huì)跟Trace span tag保持對(duì)應(yīng)來(lái)關(guān)聯(lián)請(qǐng)求調(diào)用鏈指標(biāo)和資源指標(biāo),而Trace span log會(huì)關(guān)聯(lián)保存一些詳細(xì)異常日志和框架層日志。例如PPT分享的錯(cuò)誤分析之應(yīng)用性能根因定位和全鏈路根因定位里有詳細(xì)介紹這塊的實(shí)現(xiàn)原理,進(jìn)一步在PPT效果展示中也可以看到把Metric&Trace&Log進(jìn)行關(guān)聯(lián)分析后的產(chǎn)品效果和應(yīng)用場(chǎng)景。
Q3:開(kāi)發(fā)人員自定義的日志可以采集嗎?
A3:Java主要使用基于slf4j的log4j或logback實(shí)現(xiàn),我們對(duì)此在SDK開(kāi)發(fā)了一個(gè)MDC(Mapped Diagnostic Context)擴(kuò)展,在日志里自動(dòng)帶上traceId、spanId等信息,而C++也把相應(yīng)能力集成在框架日志組件中。這些自定義日志落盤后會(huì)被采集上報(bào),在Log日志平臺(tái)中可查詢展示,我們也跟日志平臺(tái)在產(chǎn)品層做了打通聯(lián)動(dòng),會(huì)自動(dòng)帶上trace id條件來(lái)查詢?cè)撜?qǐng)求鏈路上的所有自定義日志明細(xì)。
匡凌軒虎牙直播 基礎(chǔ)保障部 SRE平臺(tái)負(fù)責(zé)人
- 負(fù)責(zé)虎牙應(yīng)用發(fā)布、元數(shù)據(jù)、計(jì)量計(jì)費(fèi)、監(jiān)控和告警等平臺(tái)建設(shè),主導(dǎo)應(yīng)用監(jiān)控和鏈路追蹤項(xiàng)目的從零到一實(shí)踐落地;曾任職歡聚時(shí)代集團(tuán),負(fù)責(zé)YY直播Web研發(fā)團(tuán)隊(duì),主導(dǎo)業(yè)務(wù)高可用、高并發(fā)分布式服務(wù)架構(gòu)設(shè)計(jì)和實(shí)現(xiàn),保障過(guò)多屆年度盛典等海量用戶業(yè)務(wù)場(chǎng)景。