|
鄭昀 最后更新于2014/11/12
關鍵詞:GoogleDapper、分布式跟蹤、鷹眼、Tracing、HBase、HDFS、
本文檔適用人員:研發(fā) 分布式系統(tǒng)為什么需要 Tracing?
先介紹一個概念:分布式跟蹤,或分布式追蹤。
電商平臺由數(shù)以百計的分布式服務構成,每一個請求路由過來后,會經(jīng)過多個業(yè)務系統(tǒng)并留下足跡,并產(chǎn)生對各種Cache或DB的訪問,但是這些分散的數(shù)據(jù)對于問題排查,或是流程優(yōu)化都幫助有限。對于這么一個跨進程/跨線程的場景,匯總收集并分析海量日志就顯得尤為重要。要能做到追蹤每個請求的完整調(diào)用鏈路,收集調(diào)用鏈路上每個服務的性能數(shù)據(jù),計算性能數(shù)據(jù)和比對性能指標(SLA),甚至在更遠的未來能夠再反饋到服務治理中,那么這就是分布式跟蹤的目標了。在業(yè)界,twitter 的 zipkin 和淘寶的鷹眼就是類似的系統(tǒng),它們都起源于 Google Dapper 論文,就像歷史上 Hadoop 發(fā)源于 Google Map/Reduce 論文,HBase 源自 Google BigTable 論文一樣。
好了,整理一下,Google叫Dapper,淘寶叫鷹眼,Twitter叫ZipKin,京東商城叫Hydra,eBay叫Centralized Activity Logging (CAL),大眾點評網(wǎng)叫CAT,我們叫Tracing。
這樣的系統(tǒng)通常有幾個設計目標:
(1)低侵入性——作為非業(yè)務組件,應當盡可能少侵入或者無侵入其他業(yè)務系統(tǒng),對于使用方透明,減少開發(fā)人員的負擔;
(2)靈活的應用策略——可以(最好隨時)決定所收集數(shù)據(jù)的范圍和粒度;
(3)時效性——從數(shù)據(jù)的收集和產(chǎn)生,到數(shù)據(jù)計算和處理,再到最終展現(xiàn),都要求盡可能快;
(4)決策支持——這些數(shù)據(jù)是否能在決策支持層面發(fā)揮作用,特別是從 DevOps 的角度;
(5)可視化才是王道。
先來一個直觀感受:
下面依次展示了 ZipKin、鷹眼、窩窩的調(diào)用鏈繪制界面。
![]() 圖1 twitter zipkin 調(diào)用鏈
![]() 圖2 淘寶鷹眼的調(diào)用鏈
![]() 圖3 京東商城hydra調(diào)用鏈
![]() 圖4 窩窩tracing調(diào)用鏈
鼠標移動到調(diào)用鏈的每一層點擊,可以看到執(zhí)行時長、宿主機IP、數(shù)據(jù)庫操作、傳入?yún)?shù)甚至錯誤堆棧等等具體信息。
淘寶如何實現(xiàn)的:
同一次請求的所有相關調(diào)用的情況,在淘寶 EagleEye 里稱作 調(diào)用鏈。同一個時刻某一臺服務器并行發(fā)起的網(wǎng)絡調(diào)用有很多,怎么識別這個調(diào)用是屬于哪個調(diào)用鏈的呢?可以在各個發(fā)起網(wǎng)絡調(diào)用的中間件上下手。
在前端請求到達服務器時,應用容器在執(zhí)行實際業(yè)務處理之前,會先執(zhí)行 EagleEye 的埋點邏輯(類似 Filter 的機制),埋點邏輯為這個前端請求分配一個全局唯一的調(diào)用鏈ID。這個ID在 EagleEye 里面被稱為 TraceId,埋點邏輯把 TraceId 放在一個調(diào)用上下文對象里面,而調(diào)用上下文對象會存儲在 ThreadLocal 里面。調(diào)用上下文里還有一個ID非常重要,在 EagleEye 里面被稱作 RpcId。RpcId 用于區(qū)分同一個調(diào)用鏈下的多個網(wǎng)絡調(diào)用的發(fā)生順序和嵌套層次關系。對于前端收到請求,生成的 RpcId 固定都是0。 當這個前端執(zhí)行業(yè)務處理需要發(fā)起 RPC 調(diào)用時,淘寶的 RPC 調(diào)用客戶端 HSF 會首先從當前線程 ThreadLocal 上面獲取之前 EagleEye 設置的調(diào)用上下文。然后,把 RpcId 遞增一個序號。在 EagleEye 里使用多級序號來表示 RpcId,比如前端剛接到請求之后的 RpcId 是0,那么 它第一次調(diào)用 RPC 服務A時,會把 RpcId 改成 0.1。之后,調(diào)用上下文會作為附件隨這次請求一起發(fā)送到遠程的 HSF 服務器。 HSF 服務端收到這個請求之后,會從請求附件里取出調(diào)用上下文,并放到當前線程 ThreadLocal 上面。如果服務A在處理時,需要調(diào)用另一個服務,這個時候它會重復之前提到的操作,唯一的差別就是 RpcId 會先改成 0.1.1 再傳過去。服務A的邏輯全部處理完畢之后,HSF 在返回響應對象之前,會把這次調(diào)用情況以及 TraceId、RpcId 都打印到它的訪問日志之中,同時,會從 ThreadLocal 清理掉調(diào)用上下文。如圖6-1展示了一個瀏覽器請求可能觸發(fā)的系統(tǒng)間調(diào)用。 ![]() 圖6-1-一個瀏覽器請求可能觸發(fā)的系統(tǒng)間調(diào)用 圖6-1描述了 EagleEye 在一個非常簡單的分布式調(diào)用場景里做的事情,就是為每次調(diào)用分配 TraceId、RpcId,放在 ThreadLocal 的調(diào)用上下文上面,調(diào)用結束的時候,把 TraceId、RpcId 打印到訪問日志。類似的其他網(wǎng)絡調(diào)用中間件的調(diào)用過程也都比較類似,這里不再贅述了。訪問日志里面,一般會記錄調(diào)用時間、遠端IP地址、結果狀態(tài)碼、調(diào)用 耗時之類,也會記錄與這次調(diào)用類型相關的一些信息,如URL、服 務名、消息topic等。很多調(diào)用場景會比上面說的完全同步的調(diào)用更為復雜,比如會遇到異步、單向、廣播、并發(fā)、批處理等等,這時候需要妥善處理好 ThreadLocal 上的調(diào)用上下文,避免調(diào)用上下文混亂和無法正確釋放。另外,采用多級序號的 RpcId 設計方案會比單級序號遞增更容易準確還原當時的調(diào)用情況。 最后,EagleEye 分析系統(tǒng)把調(diào)用鏈相關的所有訪問日志都收集上來,按 TraceId 匯總在一起之后,就可以準確還原調(diào)用當時的情況了。
圖6-2-一個典型的調(diào)用鏈 如圖6-2所示,就是采集自淘寶線上環(huán)境的某一條實際調(diào)用鏈。調(diào)用鏈通過樹形展現(xiàn)了調(diào)用情況。調(diào)用鏈可以清晰地看到當前請求的調(diào)用情況,幫助問題定 位。如上圖,mtop應用發(fā)生錯誤時,在調(diào)用鏈上可以直接看出這是因為第四層的一個(tair@1)請求導致網(wǎng)絡超時,使最上層頁面出現(xiàn)超時問題。這種調(diào) 用鏈,可以在 EagleEye 系統(tǒng)監(jiān)測到包含異常的訪問日志后,把當前的錯誤與整個調(diào)用鏈關聯(lián)起來。問題排查人員在發(fā)現(xiàn)入口錯誤量上漲或耗時上升時,通過 EagleEye 查找出這種包含錯誤的調(diào)用鏈采樣,提高故障定位速度。 調(diào)用鏈數(shù)據(jù)在容量規(guī)劃和穩(wěn)定性方面的分析 如果對同一個前端入口的多條調(diào)用鏈做匯總統(tǒng)計,也就是說,把這個入口URL下面的所有調(diào)用按照調(diào)用鏈的樹形結構全部疊加在一起,就可以得到一個新的樹結構(如圖6-3所示)。這就是入口下面的所有依賴的調(diào)用路徑情況。 ![]() 圖6-3-對某個入口的調(diào)用鏈做統(tǒng)計之后得到的依賴分析 這種分析能力對于復雜的分布式環(huán)境的調(diào)用關系梳理尤為重要。傳統(tǒng)的調(diào)用統(tǒng)計日志是按固定時間窗口預先做了統(tǒng)計的日志,上面缺少了鏈路細節(jié)導致沒辦法對超過 兩層以上的調(diào)用情況進行分析。例如,后端數(shù)據(jù)庫就無法評估數(shù)據(jù)庫訪問是來源于最上層的哪些入口;每個前端系統(tǒng)也無法清楚確定當前入口由于雙十一活動流量翻 倍,會對后端哪些系統(tǒng)造成多大的壓力,需要分別準備多少機器。有了 EagleEye 的數(shù)據(jù),這些問題就迎刃而解了。 下圖6-4展示了數(shù)據(jù)流轉(zhuǎn)過程。
![]() 圖6-4 鷹眼的數(shù)據(jù)收集和存儲
京東如何實現(xiàn)的:
京東商城引入了阿里開源的服務治理中間件 Dubbo,所以它的分布式跟蹤 Hydra 基于 Dubbo 就能做到對業(yè)務系統(tǒng)幾乎無侵入了。
Hydra 的領域模型如下圖7所示:
![]() 圖7 hydra 領域模型以及解釋
hydra 數(shù)據(jù)存儲是 HBase,如下圖8所示:
![]() 圖8 hydra 架構
窩窩如何實現(xiàn)的:
2012年,逐漸看到自建分布式跟蹤系統(tǒng)的重要性,但隨即意識到如果沒有對 RPC 調(diào)用框架做統(tǒng)一封裝,就可能侵入到每一個業(yè)務工程里去寫埋點日志,于是推廣 Dubbo 也提上日程。2013年,確定系統(tǒng)建設目標,開始動手。由于 tracing 跟 DevOps 息息相關,所以數(shù)據(jù)聚合、存儲、分析和展示由運維部向榮牽頭開發(fā),各個業(yè)務工程數(shù)據(jù)埋點和上報由研發(fā)部國璽負責。
經(jīng)過后續(xù)向榮、劉卓、國璽、明斌等人的不斷改進,技術選型大致如下所示。
基于這些數(shù)據(jù)分析和統(tǒng)計,我們就能繪制性能曲線圖,從中可以發(fā)現(xiàn)哪些時間點哪些層有性能問題,然后一路點進去,直到找到到底是哪一個調(diào)用鏈里的哪一個環(huán)節(jié)慢。
圖9 性能曲線默認圖形
還可以從每一次調(diào)用結果分析出各層的異常曲線,并按照 memcached/redis/mongodb/mysql/runtime/fail 分類查看。
圖10 異常曲線默認圖形
還可以進一步統(tǒng)計各個業(yè)務工程的訪問量、訪問質(zhì)量和平均訪問時長,并于歷史同期對比,從而快速理解系統(tǒng)服務質(zhì)量。
如上所述,窩窩的 Tracing(鷹眼) 系統(tǒng)目前已投入使用,歸并在 OAP(運維自動化平臺)里。
-over-
|
|
|