鏈家全鏈路跟蹤平臺 LTrace 設計實踐
當今的網際網路服務,通常都是用大規模的分散式叢集來實現的。服務可能來自不同的研發團隊、使用不同的程式語言來實現、執行在上千臺伺服器上。隨著鏈家的業務發展,公司的分散式系統變得越來越複雜,使用者的一次請求通常由多個系統協同完成處理,而且這些處理是發生在不同機器甚至是不同叢集上的,當請求處理髮生異常時,需要快速發現問題,並準確定位到是哪個環節出了問題,這是非常重要的。
作者|李寶銀
編輯|蔡白銀
網址|tech.lianjia.com
微信公眾號|鏈家產品技術團隊
當今的網際網路服務,通常都是用大規模的分散式叢集來實現的。服務可能來自不同的研發團隊、使用不同的程式語言來實現, 執行在上千臺伺服器上。
隨著鏈家的業務發展,公司的分散式系統變得越來越複雜,使用者的一次請求通常由多個系統協同完成處理,而且這些處理是發生在不同機器甚至是不同叢集上的,當請求處理髮生異常時,需要快速發現問題,並準確定位到是哪個環節出了問題,這是非常重要的。
為了解決這樣的問題,我們經過調研與測試,結合業界的實踐經驗 , 開發了LTrace鏈家全鏈路跟蹤平臺,有效應對上面的問題,大幅度提升工作效率。目前已經在公司多部門的各條業務線專案中得到成功應用。基於請求鏈路採集到的全量豐富資料,我們能夠直觀的瞭解到專案間的鏈路關係,就能夠進行問題的快速定位與瓶頸節點的快速排查,程式碼效能問題一覽無餘。
鏈路跟蹤,關鍵的核心是呼叫鏈,就是對一次請求進行跟蹤。通過為每個請求生成一個全域性唯一的ID,將分佈在各個服務節點上的同一次請求串聯起來,還原出更多有價值的資料。在 我們設計實現LTrace平臺過程中,遇到幾項大的挑戰。
-
穩定性挑戰。我們的業務 系統對於穩定性、效能、資源要求極其嚴格,不能有太複雜的邏輯和外部依賴,並對業務系統性能幾乎無影響,LTrace平臺的穩定性不應該對業務系統的穩定性造成任何影響;
-
高效能挑戰。目前公司存在 眾多複雜的分散式業務系統,數十 億hits 生成的鏈路資料需要及時採集儲存, 這就要求LTrace平臺具備快速的資料處理能力 ;
-
透明、易擴充套件、避免侵入業務。易於被使用方廣泛接受、低耦合是很重要的,透明性用來隱藏實現策略,避免讓使用者捲進細節,同時 具備良好的可擴充套件性 ;
-
跨語言、多協議。在公司各部門中,存在JAVA、PHP等眾多異構系統以及各種服務中介軟體,因此LTrace平臺要實現全鏈路跟蹤,必須要支援跨語言、多協議。
功能簡介
一, 呼叫鏈路
我們通過對一次請求進行還原,形成一個完整的呼叫鏈路圖,如下圖。介面中展示請求依次通過的各個服務節點的情況。比如請求經過每個服務節點的IP、傳送與響應時間點、處理結果與處理時長,網路傳輸時長、異常描述等資訊。
二,問題快速定位
再比如,我們現在可以在介面中快速的定位到問題出現的服務節點、機器IP與問題原因。以前我們遇到線上問題時,通常需要同時登入N臺機器抓日誌排查,有時還可能需要關聯上下游專案一起排查。
三,瓶頸節點
再次,我們還能夠快速定位瓶頸節點。如介面中紅框部分顯示的是鏈路呼叫的瓶頸節點,由於該節點的耗時,導致了整個鏈路呼叫的耗時延長,因此針對該節點進行優化,進而達到優化整個鏈路的效率。
四,程式碼優化
除此,我們還能夠檢測到程式碼中一些需要優化的地方。比如圖中紅框部分都是同一個介面的呼叫,甚至連請求引數都是一樣的。這種呼叫如果優化成批量請求或者相同引數只請求一次,能夠快速提升節點的服務質量。
對系統行為進行鏈路跟蹤必須是持續進行的,因為異常、超時等的發生是無法預料的,異常超時可能發生在鏈路的任何一個節點上或者一次呼叫的網路中,而且可能是難以重現的。同時跟蹤需要是無所不在,遍佈各處的,否則可能會遺漏某些重要的點。基於此LTrace設計了三個最重要的設計目標:極低的額外開銷,對應用的透明性,可擴充套件。同時產生的跟蹤資料需要可以被快速分析,這樣可以幫助我們實時獲取各節點狀態。
平臺設計
一,平臺架構
上圖中,LTrace平臺架構主要分為三部分:資料埋點上報、資料實時儲存、資料前端展示。
-
左側部分使用埋點中介軟體完成資料的採集,並非同步寫入到本地trace檔案,通過rsyslog傳送資料到訊息服務中。至於取樣策略,後面會有詳細介紹
-
中間部分資料彙集並存儲,接受訊息佇列中資料並存儲到Hbase與ES中。
-
右側部分在介面中檢索資料,分析資料進行展示。
二,基本概念
TraceId :全域性唯一,用於標識一次請求,會在RPC呼叫的網路中傳遞。
SpanId :簽名方式生成:0, 0.1, 0.1.1, 0.2。用於標識一次RPC在分散式請求中的位置,比如0.2就是0節點服務呼叫的第二個服務。
Annotation :基本標註列表,記錄一次RPC生命週期中重要時刻的資料快照。
BinaryAnnotation:業務標註列表,如果專案需要帶上業務資料(比如電話號碼、UserId等),可以將需要的資料放入。
三,呼叫鏈-Trace樹
我們將一次請求所形成的呼叫鏈路,標記成一棵Trace樹,並用全域性唯一的TraceId來標記這棵樹,如下圖:
四,呼叫鏈-Span節點
對於一次分散式請求,總會存在多次呼叫關係(如圖中箭頭線),我們將每次呼叫(箭頭線)標記成一個Span節點,並用SpanId來標記這個Span節點。
五,資料埋點
LTrace平臺對應用開發者近乎零侵入,通過為不同的異構系統提供對應的埋點中介軟體(如JAVA、PHP等)完成鏈路跟蹤。在埋點中介軟體,生成統一的TraceId等核心資料,並收集比如呼叫型別、機器IP、服務名稱、耗時、層級關係、異常資訊、業務系統的自定義資料等。
在一次分散式請求中,都有四個埋點階段,如下圖。
-
客戶端傳送(Client Send):客戶端發起請求時埋點,需要傳遞一些引數,比如TraceId、SpanId等;
-
服務端接收(Server Receive):服務端接受請求時埋點,回填一些引數,比如TraceId、SpanId等;
-
服務端響應(Server Send):服務端返回請求時埋點,將埋點資料傳遞到後端執行緒;
-
客戶端接收(Client Receive):客戶端接受返回結果時埋點,將埋點資料傳遞到後端執行緒;
六,示例
接下來我們通過一個示例進行詳細描述,如下圖,對於一次分散式請求,TraceId=12345。
在應用A收到客戶端請求時刻為0ms,響應請求時刻為69ms,即是本次請求耗費時長69ms
七,資料儲存
呼叫鏈路資料的實時查詢主要是通過Hbase,使用traceID作為RowKey,SpanId + Type(c代表客戶端、s代表服務端)能天然的把一整條呼叫鏈聚合在一起,提高查詢效率。
一,低開銷與取樣
低開銷是LTrace的一個關鍵的設計目標,如果一個工具價值未被證實但又對效能有影響的話,使用者通常不會接受它。取樣可以降低開銷,但是簡單的取樣可能導致取樣結果無代表性,LTrace通過提供多種取樣機制來滿足效能和代表性兩方面的需求。
最初我們的預設取樣策略很簡單,是在每100個請求中選擇一個進行跟蹤,這種策略對於那種請求量很高的服務來說,可以保證跟蹤到有價值的資訊;但對於那些負載不高的服務來說,可能會導致取樣頻率過低,從而遺漏重要資訊,因此我們提供了自定義取樣策略;對於異常、超時等這類極端的情況,我們認為這類資料非常有價值,因此我們決定在極端情況下全取樣;另外,對於測試人員,我們提供了可對一次請求顯示指定取樣。這樣取樣就既靈活又高度可控。
此外,通過優化訊息、快取、儲存結構、批量非同步寫入等方式,平臺效能得到大幅度提升。
通過以上取樣策略與效能優化手段,我們只需要線上原來幾十分之一的機器數量,就能夠實現原來數十倍機器相同的效果。
二,日誌TraceId繫結
-
我們通常為了便於在日誌中跟蹤一次請求,一般做法是在專案收到請求的入口放入一個RequestId。現在,應用方可以將TraceId繫結到日誌中,通過這個TraceId我們不僅能夠將應用內一次請求給串聯起來,同時還能夠用這個TraceId到上下游應用中去進行串聯。
-
有時為了知道介面都有哪些上游在使用,通過在日誌中記錄呼叫方來源。LTrace就能夠解決這個問題,通過在每次請求中輸出當前請求已經過的應用名稱列表,我們不僅能通過日誌就能夠識別這個請求的上游,還能知道這個請求所經過的所有上游應用以及請求入口。
三,支援自定義TraceId
為便於研發、測試人員進行線上線下問題的除錯、排查,LTrace平臺支援傳遞自定義TraceId,通過TraceId對問題進行跟蹤。
四,支援多執行緒等場景
業務系統中,可能會存在一些對執行緒池的使用場景,而執行緒池的切換對於TraceId的傳遞是很困難的。在LTrace平臺中,我們提供了顯示API的支援方式,保證在多執行緒的場景下TraceId也能進行上下文傳遞。
五,業務方接入簡單,穩定可靠
-
業務方接入LTrace平臺,只需要花費幾分鐘閱讀使用文件,新增幾行配置,就能夠投入使用。
-
Trace系統的可用效能夠達到99.99%以上,業務系統的穩定性不依賴LTrace平臺的穩定性,即使LTrace平臺出現異常,也不會對業務系統的穩定性造成任何影響。
經驗總結
-
使用LTrace平臺,我們可以理清系統之間關係,幫助找到關鍵系統路徑上的請求延遲,解決並提高整體效能;
-
分析請求是否正確傳送給了服務提供者,進行正確性檢查;
-
同時我們還將LTrace與公司的監控系統進行整合,如果異常發生了,我們會生成包含TraceId在內的詳細異常資料並上報給監控系統,監控服務立即發出實時的問題報警,這樣可以幫助快速發現異常以及異常的情況。