天天看點

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

作者:阿裡開發者
本章我們将以業務 Owner(小帥)的視角,逐漸了解分布式鍊路追蹤的各種基礎用法:小到單次使用者請求的異常根因診斷,大到全局系統的強弱依賴梳理,分布式鍊路追蹤都能給予确定性答案。

作者:涯海

在日常生活中,我們可能都經曆過以下場景:去醫院看病就診,但預約頁面遲遲無法打開;新款手機釋出日促銷秒殺,下單頁面一直卡住轉菊花;遊戲大版本更新,線上人數過多,導緻人物一直在“漂移”。這些問題令産品體驗變得非常差,有耐心的同學還會吐槽幾句,沒耐心的同學早已轉身離開。試想一下,作為該系統開發/運維人員,又該如何避免此類問題發生,或者快速定位止損?

關鍵路徑與多條鍊路對比

本章我們将以業務 Owner(小帥)的視角,逐漸了解分布式鍊路追蹤的各種基礎用法:小到單次使用者請求的異常根因診斷,大到全局系統的強弱依賴梳理,分布式鍊路追蹤都能給予确定性答案。

小帥作為一家電商公司訂單中心的業務 Owner,核心 KPI 就是保障建立訂單 createOrder 接口的可用性,如響應時延低于 3s,成功率大于 99.9%。一旦該接口可用性出現問題,會直接影響使用者下單行為,造成業務資損,進而影響小帥的績效和年終獎。

但建立訂單接口直接或間接依賴多個其他系統服務,如資金、位址、優惠、安全等。一旦某個下遊系統服務可用性出現問題,也會造成建立訂單失敗或逾時。為此,小帥特别頭痛,每當建立訂單接口不可用時,小帥都非常心急,卻不知該如何定位根因,隻能拉上所有下遊接口負責人一起評估,不僅費時費力,低效排查也造成業務損失進一步擴大,經常被老闆痛罵。

當小美了解這個情況後,推薦接入分布式鍊路追蹤系統,并通過一系列故障應急案例,指導如何利用 Tracing 定位問題,梳理風險,提前預警,切實提高了訂單中心的可用性。小帥經常會遇到各種使用者回報的建立訂單逾時問題,以往對此類問題頗有些束手無策。不過,接入分布式鍊路追蹤系統後,通過調用鍊準确回溯逾時請求的調用軌迹,小帥就可以輕松定位耗時最長的接口資訊,如下圖所示,A 接口逾時的主要原因是調用 D 接口導緻的。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

但如果是下面這種情況,A 調用 B,B 又調用 C。那麼,導緻 A 接口逾時的根因到底是 B 接口,還是 C 接口呢?

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

為了區分真正影響使用者體驗的 Span 耗時,我們先來了解一下關鍵路徑的概念。

關鍵路徑

如果一次 Span 調用有 t 段耗時在關鍵路徑上,那麼去掉這 t 段耗時,整條鍊路的總體耗時也會相應的縮短 t 段時間。仍以上面那條鍊路為例,灰色部分表示關鍵路徑,縮短任意關鍵路徑上的耗時都可以減少整體耗時。此時,我們可以判斷 A 接口逾時的主要原因是 C 接口導緻的。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

再來看另一種情況,如果 A 接口同一時間并行調用 B、C、D、E 接口,那麼耗時最長的 D 接口就成為關鍵路徑,如下圖所示。

但是,如果我們将 D 接口耗時減少 t1+t2 兩段時間,整體耗時卻隻減少了 t1 段時間,因為,當 D 接口耗時小于 B 接口時,D 接口就不再是關鍵路徑,而是由 B 接口取代。這就好像主要沖突被大幅緩解後,次要沖突就變成了主要沖突。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

綜上所述,我們在做耗時性能分析時,應該首先識别出關鍵路徑,然後再做針對性的優化。對于非關鍵路徑上的耗時優化不會對最終的使用者體驗産生價值。

多條鍊路對比

單條調用鍊路隻能用來分析各個接口的絕對耗時,而無法得知每個接口的耗時變化情況。但是,絕對耗時長不代表這個接口就一定有問題,比如資料存儲接口耗時通常要比單純的計算接口耗時要長,這種長耗時是合理的,無需特别關注。

是以,在診斷性能退化問題時,我們更應該關注相對耗時的變化。比如擷取同一個接口在耗時異常時段與正常時段的多條鍊路進行比對,進而發現導緻性能退化的原因。下圖展示了 A 接口的兩條不同鍊路,我們可以清楚的看到,雖然第一條鍊路的 B 接口耗時要比 C 接口耗時長,但是導緻 A 接口整體耗時從 2.6s 漲到 3.6s 的原因,其實是 C 接口的相對耗時變長了 1s,而 B 接口的相對耗時幾乎不變。是以,當 A 接口的響應時延超過 3s,不滿足可用性要求時,我們應該優先分析 C 接口相對耗時增長的原因,而不是 B 接口。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

我們再來看一個緩存未命中的例子,如下圖所示。第一條鍊路調用了5次資料庫,每一次調用的耗時都不算很長,但是 A 接口整體耗時卻達到了 3.6s。當我們比對之前未逾時的鍊路時,發現 A 接口并沒有調用資料庫,而是請求了5次緩存,整體耗時隻有 1.8s。此時,我們可以判斷 A 接口逾時的原因是調用依賴行為發生了變化,原本應該請求緩存的調用變成了請求資料庫,很可能是緩存被打滿,或者是該次請求的參數命中了冷資料,最終導緻了接口逾時。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

通過上面兩個案例,我們認識到分析性能問題時,不僅需要知道絕對耗時的多少,更要關注相對耗時的變化。當然,有經驗的同學如果對自身業務的正常鍊路形态了若指掌,就可以直接觀察異常鍊路得出結論。

關聯資訊回溯

通過前面的學習,小帥已經成功掌握了調用鍊的軌迹回溯能力,可以熟練運用調用鍊分析性能瓶頸點,快速定位異常的接口。但是,他又遇到了新的困惑,就是找到了異常接口之後,下一步該怎麼辦?比如 C 接口的耗時從 0.1s 增長到了 2.1s,導緻了上遊的 A 接口逾時。但是僅僅知道這個資訊還不夠,C 接口耗時增長背後的原因是什麼?如何解決這個問題,讓它恢複到原來的性能基線?

很多線上問題,很難隻通過接口粒度的鍊路資訊定位根因,需要結合更加豐富的關聯資料,指導下一步的行動。接下來,我們通過幾個案例,介紹幾類最典型的鍊路關聯資料,以及相應的用法。

本地方法棧

小帥負責的訂單系統,每天上午十點都會有一波周期性的業務峰值流量,偶爾出現一些逾時請求,但下遊調用耗時都很短,無法判斷逾時的具體原因,導緻這個問題一直懸而未決,為此小帥十分頭痛,隻好求助小美。正常請求與逾時請求的調用鍊路對比如下圖所示。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

由于逾時請求鍊路的相對耗時增長主要是 A 接口本身,是以,小美建議小帥啟用慢調用方法棧自動剖析功能,自動抓取逾時請求的完整本地方法棧,如下圖所示。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

通過本地方法棧,小帥得知逾時請求是卡在 log4j 日志架構 callAppenders 方法上,原來 log4j 在高并發場景的同步輸出會觸發 “熱鎖”現象,小帥将 log4j 的日志輸出由同步模式改為異步模式後,就解決了業務峰值逾時的問題。

如果小帥使用的分布式鍊路追蹤系統,并沒有提供慢調用方法棧自動剖析功能,也可以通過 Arthas 等線上診斷工具手動抓取方法棧,定位到異常方法後,再考慮将其添加至本地方法插樁埋點中,進行常态化追蹤。

自動關聯資料

基于分布式鍊路追蹤的架構攔截點,可以自動關聯多種類型的資料,比如接口請求的出/入參數,調用過程中抛出的異常堆棧,資料庫請求的執行 SQL 等等。此類資訊不影響調用鍊的形态,卻會極大的豐富鍊路的資訊,更明确的闡述為什麼會出現這樣或那樣狀況的原因。

比如小帥接到上遊業務方回報,某個新管道的商品下單總是逾時,經過排查後發現該管道訂單依賴的資料庫調用非常的慢,通過分析 SQL 明細才知道這個資料庫調用是擷取管道優惠資訊,但沒有做管道過濾,而是全量查詢了所有優惠規則,優化 SQL 查詢語句後逾時問題就解決了。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

自動關聯資料通常由分布式鍊路追蹤産品預設提供,使用者根據自身的需要選擇是否開啟即可,無需額外的操作成本。一般情況下,SQL明細和異常堆棧關聯建議常态化開啟,而記錄請求出/入參數需要消耗較大的系統開銷,建議預設關閉,僅在需要的時候臨時開啟。

主動關聯資料

小帥的老闆希望能夠定期分析來自不同管道、不同品類、不同使用者類型的訂單情況,并且将訂單接口異常排查的能力向一線營運小二開放賦能,提高使用者支援效率。正在小帥一籌莫展之際,小美建議小帥将業務資訊關聯至調用鍊上,提供業務标簽統計、業務日志軌迹排查等能力。

小帥聽取了小美的建議後,首先将管道、品類、使用者類型等業務标簽添加到分布式鍊路追蹤的 Attributes 對象中,這樣就可以分别統計不同标簽的流量趨勢,時延分布和錯誤率變化;其次,小帥将業務日志也關聯到分布式鍊路追蹤的 Event 對象中,這樣就可以檢視一次訂單請求在不同系統中的業務軌迹與資訊,即使是不懂技術的營運同學也能夠清晰的判斷問題原因,更有效的支援客戶,如下圖所示。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

由于業務邏輯千變萬化,無法窮舉,是以業務資料需要使用者主動進行關聯,分布式鍊路追蹤系統僅能簡化關聯過程,無法實作完全自動化。此外,自定義标簽和業務日志是最常用的兩種主動關聯資料類型,可以有效地将調用鍊的确定性關聯能力擴充至業務領域,解決業務問題。

綜合分析

通過本小節的學習,相信大家已經非常熟悉分布式鍊路追蹤的請求軌迹回溯能力,我們再來整體回顧一下:首先調用鍊提供了接口次元的軌迹追蹤,而本地方法棧可以較長的描述某個接口内部的代碼執行情況,自動關聯資料和主動關聯資料在不改變鍊路形态的前提下,極大的豐富了鍊路資訊,有效指導我們下一步的行動。在一些比較複雜的問題場景,需要結合以上資訊進行多角度的綜合判斷,如下圖所示。

使用篇丨鍊路追蹤其實很簡單:請求軌迹回溯與多元鍊路篩選

上一小節我們介紹了如何通過調用鍊和關聯資訊進行問題診斷,但是,細心的讀者可能會有一個疑問,整個系統有那麼多的調用鍊,我怎麼知道哪條鍊路才是真正描述我在排查的這個問題?如果找到了不相符的鍊路豈不是會南轅北轍?

沒錯!在使用調用鍊分析問題之前,還有一個很重要的步驟,就是從海量鍊路資料中,通過各種條件篩選出真實反應目前問題的調用鍊,這個動作就叫做鍊路篩選。那什麼叫多元呢?多元是指通過 TraceId、鍊路特征或自定義标簽等多種次元進行鍊路篩選。每一種篩選條件都是由日常開發/運維的場景演變而來,最為契合當下的使用方式,提高了鍊路篩選的效率和精準度。

多元度鍊路篩選

(一)基于鍊路辨別 TraceId 的篩選

提到鍊路篩選,大家很自然的就會想到使用全局鍊路唯一辨別 TraceId 進行過濾,這是最精準、最有效的一種辦法。但是,TraceId 從哪裡來?我該如何擷取呢?

如何擷取 TraceId?

雖然TraceId 貫穿于整個 IT 系統,隻不過大部分時候,它隻是默默配合上下文承擔着鍊路傳播的職責,沒有顯式的暴露出來。常見的 TraceId 擷取方式有以下幾種:

  • 前端請求 Header 或響應體 Response:大部分使用者請求都是在端上裝置發起的,是以 TraceId 生成的最佳地點也是在端上裝置,通過請求 Header 透傳給後端服務。是以,我們在通過浏覽器開發者模式調試時,就可以擷取目前測試請求 Header 中的 TraceId 進行篩選。如果端上裝置沒有接入分布式鍊路追蹤埋點,也可以将後端服務生成的 TraceId 添加到 Response 響應體中傳回給前端。這種方式非常适合前後端聯調場景,可以快速找到每一次點選對應的 TraceId,進而分析行為背後的鍊路軌迹與狀态。
  • 網關日志:網關是所有使用者請求發往後端服務的代理中轉站,可以視為後端服務的入口。在網關的 access.log 通路日志中添加 TraceId,可以幫助我們快速分析每一次異常通路的軌迹與原因。比如一個逾時或錯誤請求,到底是網關自身的原因,還是後端某個服務的原因,可以通過調用鍊中每個 Span 的狀态得到确定性的結論。
  • 應用日志:應用日志可以說是我們最熟悉的一種日志,我們會将各種業務或系統的行為、中間狀态和結果,在開發編碼的過程中順手記錄到應用日志中,使用起來非常友善。同時,它也是可讀性最強的一類日志,即使是非開發運維人員也能大緻了解應用日志所表達的含義。是以,我們可以将 TraceId 也記錄到應用日志中進行關聯,一旦出現某種業務異常,我們可以先通過目前應用的日志定位到報錯資訊,再通過關聯的 TraceId 去追溯該應用上下遊依賴的其他資訊,最終定位到導緻問題出現的根因節點。
  • 元件日志:在分布式系統中,大部分應用都會依賴一些外部元件,比如資料庫、消息、配置中心等等。這些外部元件也會經常發生這樣或那樣的異常,最終影響應用服務的整體可用性。但是,外部元件通常是共用的,有專門的團隊進行維護,不受應用 Owner 的控制。是以,一旦出現問題,也很難形成有效的排查回路。此時,我們可以将 TraceId 透傳給外部元件,并要求他們在自己的元件日志中進行關聯,同時開放元件日志查詢權限。舉個例子,我們可以通過 SQL Hint 傳播鍊 TraceId,并将其記錄到資料庫服務端的 Binlog 中,一旦出現慢 SQL 就可以追溯資料庫服務端的具體表現,比如一次請求記錄數過多,查詢語句沒有建索引等等。

剩餘60%,完整内容請點選下方連結檢視:

使用篇丨鍊路追蹤(Tracing)其實很簡單:請求軌迹回溯與多元鍊路篩選-阿裡雲開發者社群

版權聲明:本文内容由阿裡雲實名注冊使用者自發貢獻,版權歸原作者所有,阿裡雲開發者社群不擁有其著作權,亦不承擔相應法律責任。具體規則請檢視《阿裡雲開發者社群使用者服務協定》和《阿裡雲開發者社群知識産權保護指引》。如果您發現本社群中有涉嫌抄襲的内容,填寫侵權投訴表單進行舉報,一經查實,本社群将立刻删除涉嫌侵權内容。

繼續閱讀