原創聲明:本文系作者原創,謝絕個人、媒體、公衆号或網站未經授權轉載,違者追究其法律責任。
Google Dapper
首先簡單回顧一下 Google 的 Dapper,2010 年 Google 釋出 Dapper 的論文系統闡述了在複雜的、大規模分布式叢集環境下如何進行系統的跟蹤以及問題的分析與定位。通過産生一個全局唯一的 traceId 以及用 span、annotation 核心資料模型把相關調用組成一個完整的調用樹。關于 Dapper 如何做低消耗、應用級透明等細節,可以參考 Dapper 的論文。這裡主要是簡單回顧一下其核心思想,因為後續出現的分布式跟蹤産品包括本文要分析的 Facebook 的 Canopy 都有受其啟發。此文是基于2017年 Facebook 釋出的 Canopy 論文,分析其如何進行分布式跟蹤以及問題分析定位。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iNyMmZxcDN4YDM2YjM2YGO3IWZ0YGM0EWYlZmZldjZk9CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)
Span在 Dapper 跟蹤樹種短暫的關聯關系
圖檔出自 Google Dapper[1]
背景介紹
TMM
在 Canpoy 産品前,Facebook 有一個産品叫 TMM(The Mystery Machine),在其 2014 年的論文中有具體描述,簡單看一下其架構如下:
将 trace 資料存儲到 Hive、Scribe 中,然後通過 Hadoop 去跑 job 去分析計算其 trace 模型。從 1.3M 條 trace 資料中分析計算出相關模型需要 2 個小時,分析還是依賴離線計算能力上,實時性沒有那麼強。
Canopy
在網際網路分布式環境下,每一個系統在其特定場景下都有其特殊性,各自的模型都有其不同點,無法繼承如 RPC 場景、Event Loop、浏覽器頁面加載、Mobile App 等,如果為某些場景定制化,會面臨這些場景的疊代開發時間長。
另一方面一些性能分析工具不能跨系統進行分析,需要掌握每一種場景下應該使用什麼樣的分析工具以及相關資料之間的映射關系。每一種工具都有其開發周期,部署時間較長。基于此 Facebook 設計開發 Canopy 的出發點很明确主要是進行單個或跨系統間性能問題的定位,對一些問題分析的推測進行快速驗證。
Canopy 于 2015 年開始在生産環境投入使用,每天産生和處理 13 億資料量,整個産品是作為替換 TMM 在進行演進。
示 例
首先通過一個分析診斷問題的示例來看一下 Canopy 是如何去定位問題的。在此之前,先簡單說下 Facebook 頁面顯示的一些技術點。Facebook 顯示的一個完整的頁面是有很多由不同團隊開發的 page pieces 組成。Facebook 的核心架構會将它們進行合并在 web servers 和使用者的浏覽器端運作。為了優化使用者體驗,會用到一種 Early Flush 技術。Early-Flush 是服務端的一種優化技術手段,實作預測用戶端需要的資源,批量發送給用戶端。
問題描述,Facebook.com 在顯示某個頁面的初始化平均響應時間增加了300ms,如 a) 圖顯示:
圖檔出自 Facebook Canopy[2]
通過頁面加載延時看到其延時增加 300ms,但沒法定位到具體的某部分導緻其增加,在此基礎上進行進一步的拆解分析,如 b) 圖顯示:
從圖分析服務後端的 server 以及網絡相關延時都沒有發生變化,但浏覽器執行時間以及資源 (css,js 等) 的擷取時間增加了。很自然接下來去分析資源加載這塊的問題如 c) 圖所示:
圖檔出自Facebook Canopy[2]
頁面初始化顯示需要的資源發現 css 的資源下降了 5%,同時發現 Early-Flush 圖有一次 miss,導緻 css 額外加載了 10KB 的資料,如 d) 圖所示:
通過這些 metrics 已經知道問題所在(Early-Flush 沒有命中),但還不知道具體是哪一部分導緻,是以進行進一步的拆解,按 page pieces 進行分組,找到 root cause 是 UserInput 部分導緻資源的加載如 e) 圖所示:
分析 UserInput 因增加的新的功能有變動,需要一些新的資源,但 Early-Flush 元件并不知道其發生了變更,進而沒有達到的優化的效果,通過調整 Early-Flush 相關配置,性能問題進而解決。這是一個很常見的因相關配置沒有進行修改而導緻性能問題的 case,但往往這種問題很難發現定位到。
挑 戰
從上面的示例中可以看出,後面需要很豐富、詳細的 trace 以及 metrics 資料進行分析、拆解。挑戰主要展現在如下幾個方面:
- Trace資料的模型
直接操作海量的基本的性能資料是非常笨重的,擴充上也不太可能。工程師和使用的工具都必須了解底層的事件資料與各元件高層次(High level)的資料之間的映射關系。但如果建立一個高層次的固化的模型又會帶來問題:已經存在的元件,已經未來新的元件,以及三方的元件的如何支援進來。如果用多種執行模型,性能資料粒度以及品質存在大幅度變化,性能資料多樣化,無法統一。是以 trace 模型的如何管理非常關鍵。在 Dapper 中 Span 來表示樹形層次關系,在模型方面 Dapper 用 Span 來表示樹形層次
- 資料的分析
- 在資料量大的情況下提供從多特征角度進行切分、分組、過濾、組合及彙總 trace 資料
- 滿足通用以及個性化需求
對于一些常用場景的一般的用法支援的情況下,具備支援個性化需求的能力來滿足不同場景的需求。
設 計
這部分主要看 Canopy 是如何設計去滿足以及迎接這些挑戰。
Pipeline
通過管道機制,從系統生成的跟蹤資料中提取性能資料。在管道的每一個階段,給使用者的提供定制能力,并且各個元件之間的關注點是隔離的,這樣可以進行彼此的演進而不互相影響。
Canopy 的 trace 資料的收集的思路和 Dapper 類似,也是基于一些通用的元件進行 instrument,産生一個 traceId,然後在各個元件中進行傳遞,産生相關的事件,Canopy Event 會在後續介紹。
産生的事件會已上報進行收集處理,以下是其主要處理流程
④ 事件中帶有執行過程中的相關性能資料以及依賴(因果)關系資料
⑤ 收到資料在記憶體中進行聚合
⑥ 落地存儲
⑦ 如果一個請求的所有事件收齊,然後就排隊處理,在 Canopy 中所有和跟蹤相關資料都已事件方式上報,需要確定一次完整的鍊路資料已經收齊
⑧ 把 trace event 事件映射成 trace model,因為 trace 事件中包含了相關資料能以此進行模型的重構
⑨ 執行 feature 表達式,從已經模型化的 trace中抽取計算需要的特征資料,從這塊可以支援一些定制化的需求
⑩ 表達式中通過dataset配置綁定自己感興趣的過濾掉自己不需要的 trace,以及資料的輸出配置
⑪ 自己查詢 dataset,或檢視視圖和 Dashboard
⑫ 除了可以自定義 dataset,也提供了共享的(通用)dataset,一些通用的high-level特性進行查詢視圖以及 Dashboard,以及一些工具用下鑽分析。
以上介紹了 Canopy 的主體流程,通過 Canopy 的 events 把所有 trace 資料進行上報存儲,在 Instrumentation API 層都是基于 events 攜帶需要的 trace 資訊,而沒有特定的資料模型進行封裝,而在資料收集後可以進行很靈活的模型重建以及資料的抽取。
下面來看起各個相關點的設計。
Instrumentation APIs
主要職責
- 産生 traceId,并負責傳遞
- 記錄請求相關的結構層次(e.g. 何時何地,線程群組件因果關系,網絡通信)
- 收集有用的性能資料
解耦設計
- 特定的 Instrumentation 任務應該通路有限的 API,這樣降低接入門檻減少出錯,産生一些不正常的 trace 資料
- 通路這些有限的 API (封裝好相關邏輯),産生的資料相比自己去建構資料更健壯
- 從多個角度捕獲性能相關的資料,而不會破壞已經存在的邏輯。這樣可以很好的支援自定義需求的設計以及與第三方包的內建
Trace Event
Canopy中的 event 結構資訊:
Event type 可擴充,會根據 type 來做不同的處理,sequenceNumber 和 timestamp 主要用于将同一個程序或線程中的 event 排序,EventId(RandomId) 用于關聯其他有關系的 event。會在發送方記錄 eventid,traceId 和 eventid 都會透傳給接收方,在接收方會記錄發送者的 eventid。
Modeled Traces
根據 event 來建構 Modeled Trace,性能資料 High-Level 表現形式,隐藏了底層日志事件的不一緻性。
類型
- Execution units:執行線程
- Blocks:execution unit中計算段(Segments of computation within an execution unit)
- Points:一個Block中即時發生的events
- Edge:points間的因果關系
可以表示程序間或機器間的因果關系也可用于表示同一程序中的execution units或blocks。非常适合以下模式
長時間運作的執行單元間的流,雙向通訊,應用級别block依賴
Trace Datasets
- Trace 資料衍生出來的資料集,囊括了很多Traces資料的資訊
性能分析的主要入口點(面向工程師)
- Feature(trace中一個元素的label或聚合值或一些結構關系) 通過抽取函數(抽取函數是無狀态的且一條trace記錄執行一次)産生
Trace Dataset 表現形式
基于這些豐富或自定義的 trace 資料集來支援一般以及個性化需求。
小 結
本文介紹了 Facebook Canopy 在面對海量 trace 資料以及各種環境下,如何去設計端到端的性能分析産品。縱觀下來,其設計特點是解耦的設計,trace 事件資料沒有綁定到固定的資料模型中,資料處理環節支援靈活的 feature 抽取,形成不同的 trace dataset 資料集來達到不通場景的需求。
參考
[1] Dapper, a Large-Scale Distributed Systems Tracing Infrastructure
[2] Canopy: An End-to-End Performance Tracing and Analysis System