進階篇丨鏈路追蹤(Tracing)很簡單:常見問題排查

經過前面多篇內容的學習,想必大部分同學都已經熟練掌握分佈式鏈路追蹤的基礎用法,比如回溯鏈路請求軌跡,定位耗時瓶頸點;配置核心接口黃金三指標告警,第一時間發現流量異常;大促前梳理應用上下游關鍵依賴,聯繫相關方協同備戰等等。隨着深入使用鏈路追蹤技術,問題發現與診斷方面的能力想必都有大幅提升。

但實際生產過程中的問題可能更加棘手:

比如接口偶發性超時,調用鏈只能看到超時接口名稱,看不到內部方法,無法定位根因,也難以復現,怎麼辦?

比如接口調用成功,但是業務狀態異常,導致結果不符合預期,如何排查?

比如大促壓測時或發佈變更後,發現 CPU 水位非常高,如何分析應用性能瓶頸點,針對性優化?

比如同一份代碼,本地調試都正常,但是發佈到線上環境就報錯,如何定位代碼行爲不一致的原因?

諸如此類的難題它們好像不屬於鏈路追蹤的範疇,卻又與鏈路追蹤有着千絲萬縷的聯繫。

鏈路追蹤是可觀測不可分割的一部分,我們不應該人爲的劃分邊界,而是要打破數據孤島,緊密結合其他可觀測技術,以提高系統穩定性爲目標,最大化的發揮鏈路追蹤的關聯價值。

本小節通過對經典案例的解讀,大家將掌握鏈路追蹤與其他可觀測技術結合應用的竅門,打破對鏈路追蹤固有的認知,深入理解鏈路追蹤在可觀測領域的關聯價值。

01 應用日誌關聯:一次訂單支付失敗行爲的全息排查

【問題描述】某天,收到了來自前線小二反饋的客戶投訴,訂單支付一直失敗,客戶情緒非常焦躁,需要儘快給予回覆,投訴工單記錄了支付失敗的訂單號 213589741238xxxx。

【難點分析】訂單支付接口依賴了多個下游服務,接口調用本身是成功的,但是業務報錯導致支付失敗。而且只有訂單中心的應用日誌記錄了訂單號,下游應用日誌沒有訂單號信息,無法直接通過訂單號進行全應用掃描。

【解決思路】利用鏈路追蹤的上下游追溯能力進行信息串聯。

a. 通過失敗訂單號檢索訂單中心的應用日誌,並找到日誌中關聯的 TraceId。

b. 通過 TraceId 查詢全鏈路調用軌跡,找到當次請求依賴的上下游調用。

c. 通過查詢上下游應用跟當次請求相關的應用日誌,定位到訂單支付失敗原因,原來是優惠券失效導致的。

【延伸思考】通過上述案例,可以發現全息排查的前提是實現 TraceId 與應用日誌的雙向綁定,目前業界的主流做法是將 TraceId 添加到應用日誌中實現關聯。在鏈路多維篩選小節中,我們介紹了兩種在日誌輸出中添加 TraceId 的方式:基於 SDK 手動埋點與基於日誌模板自動埋點,感興趣的同學可以詳細閱讀相關章節的介紹。

02 慢調用方法棧自動剖析:偶發性慢調用,如何定位導致問題的那一行代碼?

【問題描述】負責穩定性的同學對這種場景應該不陌生:系統在夜間或整點促銷時會出現偶發性的接口超時,等到發現問題再去排查時,已經丟失了異常現場,並且難以復現,最後只能不了了之。上述場景重複上演直至釀成故障,最終蒙受巨大的業務損失。

【難點分析】開源的鏈路追蹤實現通常只能記錄超時的接口,無法細化到具體的方法棧,開發同學不知道該如何修復。而偶發性異常沒有規律,又難以復現,很難通過手動 jstack 或者 Arthas 等在線診斷工具去精準定位根因。

【解決思路】爲鏈路追蹤埋點添加回調函數,自動記錄慢請求的本地方法棧,真實還原代碼執行的第一現場。如下圖所示,當接口調用超過一定閾值(比如2秒),會啓動對該次慢請求所在線程的監聽,直至該次請求結束後立即停止監聽,精準保留該次請求生命週期內所在線程的快照集,並還原完整的方法棧及耗時,最終定位耗時主要消耗在請求數據庫連接 getConnection 方法上,通過增加數據庫連接數可以解決響應慢的問題。

【延伸思考】目前主流的開源鏈路實現並不支持慢調用方法棧自動剖析,只有少數商業化產品(如阿里雲 ARMS)支持了該特性。爲了能夠獲取完整的方法棧信息,傳統的鏈路插樁(Instrument)並不適合獲取方法棧監聽,只能利用採樣法(Sampling)進行堆棧聚合,但全局採樣的高開銷很難實現常態化自動監聽,必須結合鏈路追蹤埋點,精準定位慢調用所在線程與生命週期,低成本實現精準、輕量級的採樣監聽。

03 CPU利用率高“三步排查法”:大促前夕壓測發現CPU水位非常高,如何分析應用性能瓶頸點,針對性優化?

【問題描述】雙十一大促前夕,部門組織了核心應用全鏈路壓測,然而小玉負責的訂單中心在第一波壓測流量脈衝下 CPU 利用率瞬間飆升到 90% 以上,接口調用大量超時,成爲了全鏈路性能瓶頸,導致壓測活動草草結束,主管責令她在一週內限期完成優化。

【難點分析】CPU 利用率高可能是單純的機器資源不足,也可能是不合理的代碼導致的。基礎的 CPU 監控只能反映問題,無法定位根因,缺乏資源到代碼的映射關係,導致很多同學無法簡單直接的進行代碼優化,只能盲目擴容。

【解決思路】以 Java 應用爲例,我們可以利用工具一步步定位導致 CPU 利用率高的異常代碼片段,主要分爲以下三步:

a. 查看 CPU 基礎監控,確定流量洪峯與 CPU 利用率飆升曲線在時間上是否吻合,CPU 利用率上漲的主要原因是否爲用戶態 CPU 上漲,排除宿主機“超賣”,磁盤故障等硬件因素的干擾。

b. 查看線程分析監控,判斷是哪一類線程(池)消耗的 CPU 最多,以及此類線程的 CPU 耗時曲線是否與 CPU 利用率曲線吻合,初步定位異常線程類別。

c. 通過 CPU 診斷工具,分析異常時段內的 CPU 火焰圖,確定 CPU 佔比最高的方法調用棧,進行鍼對性的優化。如下圖所示,消耗 CPU 99.7% 佔比的方法是 CPUPressure.runBusiness() 方法。

【延伸思考】

  • CPU 分析的難點是缺乏有效的工具,能夠給出資源到代碼之間的映射關係,直接定位異常代碼片段,指導研發同學進行優化。此外,診斷行爲相對於問題發生往往是滯後的,工具必須具備常態化運行,自動保留異常現場的能力。如何平衡現場快照的信息度與工具自身的資源開銷,非常考驗產品設計與技術實現能力,許多商業化產品在這一點上存在着不小的差距。
  • 如果某個核心方法的代碼邏輯變更頻繁,容易造成性能退化,還可以爲其添加鏈路埋點,進行常態化的監聽。更進一步,還可以將該方法關聯的 CPU 開銷展示在調用鏈上,提高診斷的效率,如下圖所示。

04 內存異常“三步排查法”:應用頻繁 FGC 或是內存崩潰,如何定位根因,保障服務可用性?

【問題描述】FullGC 絕對是 Java 應用最常見問題之一,對象創建過快、大對象分配、內存泄漏等各種原因都會導致 FGC。比 FGC 更嚴重的是內存崩潰,比如不合理的使用堆外內存 DirectBufferMemory,可能導致 OOM(OutOfMemoryError),JVM 崩潰,服務不可用等嚴重後果。

【難點分析】導致內存異常的原因千奇百怪,最有效的方式就是記錄內存異常的現場快照。但是內存快照的記錄成本非常高,很難常態化自動保存。等到真正出問題的時候又可能來不及記錄了,這就導致內存診斷變得非常困難。

【解決思路】以 Java 應用爲例,結合工具由易到難逐步定位內存異常原因,主要分爲以下三步:

a. 查看 JVM 監控,分析新生代、老年代、Metaspace、DirectBuffer 等內存變化,初步定界內存異常的類型,以及確認是否存在內存泄露現象。

b. 通過輕量化內存診斷,分析異常時段的內存對象分配火焰圖,定位分配內存最多的方法,進行重點分析。如下圖所示,99.92% 的內存是通過 AllocMemoryAction.runBusiness() 方法申請的。

c. 分配內存多,並不代表常駐內存多,大部分對象可能通過 YGC 就釋放掉了。因此,針對一些疑難雜症,還需要使用 HeapDump 來進行最終定位。

【延伸思考】輕量化內存診斷是介於 JVM 監控與 HeapDump 之間的折中方法,可以常態化記錄內存申請信息,在大部分場景可以有效工作。與 CPU 診斷類似,如果某個核心方法頻繁申請內存,可以考慮對其添加鏈路埋點,並關聯內存申請與 GC 等信息,提高調用鏈信息集成度與診斷效率。

05 白屏化在線診斷:程序運行不符合預期,本地調試成功的代碼,發佈到線上就報錯,怎麼辦?

【問題描述】本地調試通過的代碼,一旦發佈到線上環境就各種報錯,到底哪裏出了問題?相信開發同學都經歷過這樣的噩夢。導致這種問題的原因有很多,比如 Maven 依賴多版本衝突,不同環境動態配置參數不一致,不同環境依賴組件差異,本地無法模擬線上環境真實流量參數或壓力等等。

【難點分析】本地、日常、預發、生產,不同環境之間總存在着這樣或那樣的一些差異,導致同一份代碼表現出不同的行爲或異常,必須在當前環境進行診斷定位。傳統的遠程 debug 模式操作複雜,安全風險高。而類似 Arthas 這種單機診斷工具需要黑屏登錄,命令行交互,使用起來也比較麻煩。

【解決思路】在 APM 探針中內置在線診斷模塊,通過控制檯進行白屏化交互,按照診斷場景進行命令封裝,進一步簡化操作成本。比如通過調用鏈找到異常調用的全路徑類名與方法後,對該方法執行源碼解析、出入參攔截等經典診斷命令,實時查看當前程序運行態的源代碼、出入參、執行方法棧與耗時、靜態對象或動態實例的值等等,讓在線調試就像本地調試一樣方便,一鍵定位錯慢根因。

【延伸思考】白屏化只是在線診斷的第一步優化,如何進一步降低診斷開銷與風險,從單機診斷升級爲集羣診斷,從主動式診斷升級爲自動觸發式診斷,從特定語言(如Java)向全語言覆蓋,需要更多新技術與產品的迭代。

06 探索式鏈路分析與監控:1秒戰役,如何常態化治理入口請求慢響應問題?

【問題描述】入口請求的響應時延直接影響着終端用戶的體驗,根據 Google 的統計,時延每增加 500 毫秒就會導致 20% 的訪問量流失,而 Amazon 也有類似的發現,每增加 100 毫秒的時延就會導致 1% 的銷售額下降。因此,很多企業 IT 服務都會制定嚴格的入口服務響應時延 SLA,儘可能保證終端用戶的訪問能夠得到快速響應。但是,影響時延的因素有很多,流量不均、單機故障、程序異常、依賴組件瓶頸等都會顯著影響入口請求的時延,如何低成本的進行常態化治理呢?

【難點分析】不同企業、不同類型的服務對時延的要求不盡相同,影響時延的維度特徵也比較發散,很難通過開源或商業化產品內置的基礎監控實現慢請求的篩選與分析。基於明細數據的分析雖然比較靈活,但是全量檢索的成本比較高,當分析規則較多時,不適用於常態化的監控與告警,無法主動通知時延退化風險。

【解決思路】我們需要將鏈路分析與監控的能力進行結合,既能靈活滿足用戶自定義的查詢分析訴求,還能將用戶的分析規則進行固化,生成自定義鏈路指標,實現常態化的監控與告警。

a. 通過 TraceExplorer 對鏈路明細數據進行在線篩選與分析,可以根據業務需要靈活設置各種條件,比如查看特定入口應用大於 3 秒的慢請求分佈在哪些接口,如下圖所示。

b. 保存剛剛設置的查詢分析規則,便於後續一鍵快速分析。不過這一步還是基於鏈路明細數據,分析成本比較高,並且結果的準確性強依賴鏈路數據採樣率,不適合常態化監控與告警。

c. 爲了實現低成本的常態化監控與告警,還可以將查詢分析規則下推,在數據處理端生成新的自定義鏈路指標(預聚合)。

【延伸思考】在實際生產環境中,服務通常是標準化的,但業務卻需要分類分級。同樣的訂單服務,我們需要按照類目、渠道、用戶等維度進行分類統計,實現精細化運營。比如,對於線下零售渠道而言,每一筆訂單、每一個 POS 機的穩定性都可能會觸發輿情,線下渠道的 SLA 要求要遠高於線上渠道。那麼,我們如何在通用的電商服務體系中,精準的監控線下零售鏈路的流量狀態和服務質量呢? 答案就在鏈路數據的自定義標籤 Attributes 中,比如,我們在入口服務針對線下訂單打上一個 {"attributes.channel": "offline"} 的標籤,然後再針對不同門店、用戶客羣和商品類目分別打標。最後,通過對 attributes.channel = offline 進行過濾,再對不同的業務標籤進行 group by 分組統計調用次數、耗時或錯誤率等指標,就可以快速的分析出每一類業務場景的流量趨勢與服務質量。

07 智能根因定位:如何讓新手具備“專家級”診斷能力,快速定位經典問題根因?

【問題描述】線上應用風險主要分爲“錯”、“慢”兩大類。其中“錯”的原因通常是程序運行不符合預期, 比如 JVM 加載了錯誤版本的類實例,代碼進入異常分支,環境配置錯誤等。而“慢”的原因通常是資源不足, 比如突發流量導致 CPU 打滿,微服務或數據庫線程池被耗盡,內存泄漏導致持續 FGC 等等。無論是“錯”問題,還是“慢”問題。從用戶的角度,都是希望能夠快速定位根因,及時止損,並消除隱患。但是,絕大部分線上問題無法僅通過鏈路追蹤的基礎能力就能有效定位並解決,需要結合資源監控、代碼診斷等多方面能力,對排查人員的經驗和能力要求非常高,如何讓更多同學快速具備“專家級”診斷能力呢?

【難點分析】一個錯誤的運維動作可能引發大範圍的可用性故障,線上環境的低容錯性與高時效性特徵,對於根因定位的精度與速度要求很高。因此,很多基於概率的機器學習算法並不適用於運維領域。此外,一個具有豐富經驗和能力的診斷專家需要大量的時間沉澱與案例“餵養”,在互聯網快速迭代的背景下,只有少部分公司能夠培養出此類稀缺人才,無法快速批量複製。

【解決思路】線上應用風險是有一定的跡象可循的,針對常見經典問題,我們可以基於領域專家經驗結合比較成熟的算法,實現經典問題的自動根因定位或定界,提高診斷效率,降低診斷門檻。比如我們首先通過時序異常檢測算法,識別到 A應用下單接口耗時突增,檢查 A 應用自身資源並沒有發現瓶頸,然後檢查下單接口依賴服務,發現下游接口耗時突增,逐級追溯後最終定位到 C 應用有 2 臺機器 CPU 利用率過高,達到 95%+,對 C 應用進行緊急擴容後恢復。

【延伸思考】針對運維領域的經典問題根因定位,在現階段更適合採用以專家經驗爲主,算法爲輔的手段,本質上是人工檢查流程的自動化沉澱,還遠未達到智能化的程度,也不該盲目追求“高大上”的算法,而應以實用爲主,優先解決數據完整度與豐富度。

08 小結

鏈路追蹤(Trace)最大的價值在於“關聯”,無論是從數據層面關聯應用日誌(Logs)、關鍵事件(Events)、性能指標(Metrics)或診斷工具(Profiling),還是從系統層面關聯用戶終端、網關、應用、中間件、容器與基礎設施,鏈路追蹤最大的價值不在於自身,而在於關聯性的場景化呈現,讓我們一起來繼續挖掘更多更有價值、也更有意思的用法吧!

作者:涯海

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

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