天天看點

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

作者:dbaplus社群

綜述

位元組跳動在發展過程中,逐漸形成了十分複雜的超大規模微服務體系,對後端整體的可觀測性解決方案提出了極高的要求。為了解決這個問題,基礎架構智能運維團隊自研鍊路追蹤系統,将海量 Metrics/Trace/Log 資料進行整合與統一,并在此基礎上實作了新一代的一站式全鍊路觀測診斷平台,幫助業務解決監控排障、鍊路梳理、性能分析等問題。本文将會介紹位元組跳動鍊路追蹤系統的整體功能和技術架構,以及實踐過程中我們的思考與總結。

一、什麼是分布式鍊路追蹤(Trace) ?

1、M T L的關系

可觀測性的三大基礎資料是 Metrics / Log / Trace。說到這三大件,可能大家會想到當需要監控變化趨勢和配置告警時就去用 Metrics;當需要細查問題時去查 log;對于微服務數量較多的系統,還得有 Trace,Trace 也可以看做一種标準結構化的 log,記錄了很多固定字段,例如上下遊調用關系和耗時,檢視上下遊調用關系或者請求耗時在鍊路各節點上的分布可以檢視 Trace。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

但是如果帶着孤立的觀點去用這些資料的話,資料的價值會大大降低。舉例一個常見的場景,通過 Metrics 得知某服務 SLA 降低,錯誤率上升,怎麼去排查根因呢?先去找錯誤日志吧,可是我看到的錯誤日志是不是真的和這個錯誤率上升有關系呢?得翻翻代碼看看這些錯誤日志都是哪裡打出來的,代表什麼意思。再去找找有沒有錯誤 Trace?找出來的 Trace 也不太确定是不是和這個錯誤率上升有關系,還是得看代碼确認下。終于通過一行行的代碼和資料比對,确認到這個錯誤是下一層服務傳回給我的,把那個服務的負責人拉進來一起排查吧,然後這個群越拉越大,更多的人被拖進來一層一層地查下去,最終定位到是某個底層服務上線了一個變更導緻 Panic,錯誤層層向上傳播導緻服務 SLA 降低。

這個過程很不美好,需要工程師了解每一項資料的底層邏輯,才能充分利用它們去解決具體問題。而在複雜的大規模微服務系統中,沒有單個工程師能夠做到熟悉每一個微服務的底層邏輯,是以複雜微服務系統的排障和觀測往往是一項有挑戰的困難工作。

2、Trace 是資料的連結紐帶

如果所有微服務的監控資料都是遵循統一模型和語義規範并且天生高度關聯的呢?

在軟體系統中,每秒鐘有無數的 Context 在流動。這些 Context 可能是一個實時線上請求,也可能是一個異步處理任務。每個 Context 都會在多個微服務節點中持續傳播才能最終完成。所有的監控資料(包括 Metric, Log 等)都源自于某一個 Context。Trace 就是這個 Context 的資料載體,通過标準化的資料模型,記錄 Context 在多個微服務中的全部執行過程,并沿途關聯上此 Context 上發生的所有事件(包括 Metric, Log 等)。

再回到剛才那個 Case,當我們對某個 Metric 波動發生興趣時,可以直接将造成此波動的 Trace 關聯檢索出來,然後檢視這些 Trace 在各個微服務中的所有執行細節,發現是底層某個微服務在執行請求過程中發生了 Panic,這個錯誤不斷向上傳播導緻了服務對外 SLA 下降。如果可觀測平台做得更完善一些,将微服務的變更事件資料也呈現出來,那麼一個工程師就可以快速完成整個排障和根因定位的過程,甚至不需要人,通過機器就可以自動完成整個排障和根因定位過程。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

Trace 不僅僅是用來檢視耗時分布甘特圖的工具,也是海量監控資料的 Context 連結紐帶。基于可靠關聯的 Metric / Trace / Log 資料,也建構出強大的可觀測性能力,回答監控排障、SLO 調優、架構梳理、流量估算、智能化故障歸因等衆多複雜問題。

Trace 的采集以及跨服務程序的 Context 傳遞一般是由微服務架構等基礎設施自動完成的,但是要實作最佳效果也需要所有研發工程師的了解和配合。研發工程師在編碼的過程中應當有意識地在所有代碼執行過程中持續傳遞 Context。比如在 Golang 中,context.Context 需要在所有函數調用中作為參數持續傳遞;在 Java 中,一般預設用 Threadlocal 作為 Context 的存儲載體,但是如果有多線程或者異步的場景,則需要開發者自行對 Context 進行顯式的傳遞,否則上下文就斷了,難以實作有效的追蹤和監控。

二、位元組鍊路追蹤系統的挑戰與機遇

位元組跳動在發展過程中,逐漸形成了十分複雜的超大規模微服務體系,對後端整體的可觀測性解決方案提出了極高的要求。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南
我們面臨的挑戰包括:

  • 線上流量巨大
  • 微服務數量巨大,調用關系複雜,疊代變化快
  • 研發團隊龐大,分工複雜

目前位元組跳動有巨大的流量,衆多的活躍微服務、容器執行個體數,以及龐大的研發團隊。一個複雜業務鍊路動辄涉及數百個微服務,有一線業務,有中台,也有基礎設施,不同微服務由不同的研發團隊開發,同時還有各類橫向團隊負責整體架構的品質、穩定性、安全和效率等相關工作。不同團隊對鍊路追蹤系統都會有不一樣的訴求。

同時我們也有着難得的機遇:

  • 微服務架構高度統一
  • 微服務高度容器化,環境統一
  • 存儲/中間件等基礎設施高度統一

得益于長期的統一基建工作,位元組全公司範圍内的所有微服務使用的底層技術方案統一度較高。絕大部分微服務都部署在公司統一的容器平台上,采用統一的公司微服務架構和網格方案,使用公司統一提供的存儲元件及相應 SDK。高度的一緻性對于基礎架構團隊建設公司級别的統一鍊路追蹤系統提供了有利的基礎。

三、位元組鍊路追蹤系統的目标

面對這樣的現狀,位元組鍊路追蹤系統圍繞着一些目标展開建設。我們的功能性目标主要包括這幾個方面:

  • 統一資料模型與語義:統一資料模型和語義規範,對所有主流架構/元件進行預設埋點中間件的替換更新,建立 Metrics / Trace / Log 可靠關聯關系。
  • 開放自定義:統一模型的基礎上,充分開放自定義能力,滿足不同業務場景的監控追蹤需求。
  • 中心化配置管控:中心化動态管理采樣、染色、熔斷限流、索引、脫敏保密等各類政策。
  • 一站式觀測平台:提供從 SDK 到采集、計算、存儲、查詢和産品化互動的完整解決方案,基于高品質基礎資料,建構一站式觀測平台,提升監控排障、SLO 調優、架構梳理、容量管理等場景的能效。

在功能性目标的背後,我們追求的技術目标主要圍繞這幾個方面:

  • 業務內建開銷最小化:內建開銷包括業務接入的改造成本和接入後帶來的 Overhead 開銷。大範圍的鍊路追蹤能夠成功覆寫推廣,必須保證将內建開銷降到最低。
  • 平衡存儲效率與檢索需求:需要以有限的機器預算完成較大資料量的處理和存儲,保證資料從産生到可被檢索的延遲在分鐘級以内,檢索響應速度在秒級以内。
  • 多機房容災完備性:需要優先考慮當發生斷網或擁塞、機房當機等災難場景,業務急需觀測線上狀況時,保持可用。
  • 最小化架構與依賴複雜度:位元組在海内外有衆多機房,需盡可能最小化整體架構的複雜度和第三方依賴的複雜度,否則多機房的部署運維包括容災完備性保障會非常困難。

四、位元組鍊路追蹤系統的實作

1、資料采集

1)資料模型

統一的資料模型是 Trace 的基礎,位元組鍊路追蹤系統的資料模型設計借鑒了 opentracing 和 CAT 等優秀的開源解決方案,結合位元組内部實際生态和使用習慣,使用如下資料模型:

  • Span: 一個有時間跨度的事件,例如一次 RPC 調用,一個函數執行。
  • Event: 一個沒有時間跨度的事件,例如一條 log,一次 panic。
  • Metric: 一個帶多元 tag 的數值,例如一個消息體的大小,一個訂單的價格。
  • Trace: 一個請求上下文在多個分布式微服務節點的完整執行鍊路。
  • Transaction: 一條 Trace 在單個服務節點上的所有 Span / Event / Metric 對象構成的樹形結構消息體。Transaction 是 Trace 資料的處理和存儲的最小機關,緊湊的資料結構有利于節約成本和提高檢索性能。
位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

下圖展示了使用位元組鍊路追蹤系統 SDK 埋 Trace 的代碼示例。注意其中 Context 貫穿整個請求生命周期,在程序内和跨程序間持續傳遞,将資料串聯起來。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

繼續這個示例,我們結合下圖闡述一下如何基于這套模型将 Metric / Trace / Log 進行可靠關聯的。

①Metric 關聯 Trace:

  • 每個 Span 會有内置的頻次/耗時/失敗率 Metric 統計時序,Rpc/Mq 場景的 Span 還會有 SendSize/RecvSize/MqLag 等内置統計時序。Span Tag 和 Metric Tag 一一對應,以此為依據可以将 Span 時序名額與 Trace 中的 Span 可靠關聯。
  • 每個 Event 不僅會挂載在 Span 上,也會有内置的頻次 Metric 統計時序。Event Tag 與 Metric Tag 一一對應,以此為依據可以将 Event 時序名額與 Trace 中的 Event 可靠關聯。
  • 每個 Metric 不僅會挂載在 Span 上,也會按 Metric 類型輸出 rate/timer/store 等各類統計時序,兩邊 Tag 一一對應,以此為依據可以将 Metric 時序名額與 Trace 中的 Metric 對象可靠關聯。

②Trace 關聯 Log:

  • Log SDK 會将 Context 中的 TraceID 和 SpanID 寫入日志頭中,通過 TraceID 和 SpanID 與 Trace 建立可靠關聯。
位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

2)語義規範

僅有統一的抽象資料模型還不夠。如果每個服務都五花八門的随意打 tag 沒有統一标準,那麼即使有統一抽象模型也很難建設高品質的觀測平台。必須對 HTTP Server, RPC Server, RPC Client, MySQL Client, Redis Client, MQ Consumer, MQ Producer 等各類主流場景都進行統一的語義規範,確定不同語言不同架構在相同場景下上報的資料遵循統一語義規範,才能夠真正擷取高品質的可觀測性資料。

語義規範沒有唯一标準,下面給出位元組内部目前使用的部分語義規範作為參考示例。

①通用基礎字段

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

②場景化語義規範示例:RPC Client 場景

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

3)采樣政策

由于位元組整體線上流量非常大,微服務數目衆多,不同微服務的性能敏感度、成本敏感度和資料需求各有不同,例如有些服務涉及敏感資料,必須有非常完整的追蹤資料;有些服務性能高度敏感,需要優先控制采樣數最小化 Overhead;測試泳道、小流量灰階或者線上問題追查等場景會需要不同的采樣政策;正常流量和發生異常的流量也需要不同的采樣政策。是以靈活的采樣政策以及調控手段非常必要。位元組鍊路追蹤系統主要提供了如下幾種采樣模式:

  • 固定機率采樣+低流量接口兜底采樣:預設以 Logid 作為采樣種子,按固定機率進行采樣。對于流量較低的接口,按固定機率采樣難以命中的,SDK 會自動按一定的時間間隔進行兜底采樣,確定低流量接口也有一定數目的請求被采集。
  • 自适應機率采樣:按機關時間對每個接口采集一定數目的 Transaction 為目标,例如 100 條/min,SDK 自動根據目前 QPS 動态計算采樣率進行采樣。流量較低或不穩定的服務建議采取這種模式。
  • 染色采樣:對特定的請求添加染色标記,SDK 檢測到染色标對該請求進行強制采樣。
  • PostTrace 後置采樣: 當一個 Trace 一開始未命中采樣,但在執行過程中發生了一些令人感興趣的事(例如出錯或時延毛刺)時,可以在 Trace 中間狀态發起采樣。相較于先全采再後置采樣,此方案開銷極低。PostTrace 是前置機率采樣的一個重要補充,可以針對性地采集到異常鍊路,相比于先全采後 tail-based sampling 方案其開銷是極小的。但 PostTrace 的缺點隻能采集到 PostTrace 時刻尚未結束的 Span,是以資料完整性相較前置采樣有一定損失。

我們結合一個示例來更好的了解什麼是 PostTrace。左圖是一個請求,按照阿拉伯數字辨別的順序在微服務間發生了調用,本來這條 trace 沒有采樣,但是在階段 5 時發生了異常,觸發了 posttrace,這個 posttrace 資訊可以從 5 回傳到 4,并傳播給後續發生的 6 和 7,最後再回傳到 1,最終可以采集到 1,4,5,6,7 這幾個環節的資料,但是之前已經結束了的 2、3 環節則采集不到。右圖是我們線上的一個實際的 posttrace 展示效果,錯誤層層向上傳播最終采集到的鍊路的樣子。PostTrace 對于錯誤鍊傳播分析、強弱依賴分析等場景有很好的應用。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

這些采樣政策可以同時組合使用。需注意,采樣不影響 Metrics 和 Log。Metrics 是全量資料的聚合計算結果,不受采樣影響。業務日志也是全量采集,不受采樣影響。

4)中心化配置管控

為了提高效率,友善不同團隊高效工作,位元組鍊路追蹤系統提供了豐富的中心化配置管控能力,核心能力包括以下幾個方面:

  • 采樣政策:支援業務按照不同的叢集、接口、機房、部署階段設定不同的機率采樣政策;也可以動态設定染色、PostTrace 觸發條件。
  • 自定義索引:不同的架構和場景會有不同的預設索引字段,也支援業務按需在預設索引的基礎上為自定義字段建立索引。
  • 熔斷保護:SDK 預設配備多種熔斷保護機制確定 Trace 采集不會占用過多資源影響主線功能,同時允許業務根據實際情況對相關的熔斷參數進行動态調整。
  • 脫敏保密:業務可以按需對 Trace 資料進行脫敏和保密。

2、整體架構

1)整體架構

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

位元組鍊路追蹤系統從資料接入側、消費存儲到查詢整體子產品架構如上圖所示。這裡說一些技術細節:

  • 私有協定資料流,性能更極緻:從 SDK 到最終寫入存儲,整體資料流采用私有協定,資料流中各環節僅需解碼部分 header 即可完成處理,無需解碼所有内容,可以節約大量的中間環節資源,降低延遲時間。
  • 底層本高吞吐的位元組自研日志存儲:以較低的存儲成本實作較高的寫入速度和查詢性能,用于支援各類 Trace 線上檢索場景。
  • 單元化架構保障多機房容災完備性:整體采用單元化架構,節約機房間網絡帶寬,在部分機房間網絡故障或單機房當機時保持高可用。
  • 精細靈活的中心化調控能力:統一的配置中心向整個資料流各階段下發各類動态配置發并實時生效。
  • 兼顧線上實時查詢與計算分析:如架構圖所示,資料流主要分兩條,一條負責資料的線上存儲和實時查詢,要求鍊路盡可能短,追求性能極緻,壓低延遲時間,保證資料從産生到可檢索要盡可能快+高可用;另一條是計算分析流,對延遲的要求相對較低,但是需要滿足各類場景化的計算分析需求,與公司數倉平台有較好的內建。
  • 中繼資料采集與安全過期:從 Trace 資料流中可以采集到準确度和時效性很高的中繼資料,例如每個微服務有哪些活躍接口,使用了哪些架構元件等資訊,為多個第三方系統例如監控告警和服務治理等平台提供支援。

2)多機房容災完備性

前面講目标時提到,鍊路追蹤系統作為一個可觀測性基礎設施,需要優先考慮當發生斷網或擁塞、機房當機等災難場景,業務急需觀測線上狀況時,保持可用。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

位元組鍊路追蹤系統采用單元化部署機制,寫入資料流上各機房間無通信,頂層查詢子產品部署在彙聚機房(同時在主機房部署備用查詢節點),查詢時向各機房發起檢索并合并結果。

  • 寫入流主機房間無資料通信,主機房間發生斷網時,功能不受損。
  • 當發生單機房當機或孤島時,可執行預案在查詢側屏蔽掉故障機房,保證其他機房資料可用。
  • 當頂層查詢子產品所在的機房當機或斷網時,可執行預案将查詢切到備用機房查詢節點繼續提供服務。

3)分析計算

除了基礎的實時檢索能力以外,場景化的資料聚合分析計算也是鍊路追蹤系統的一個重要需求,目前位元組鍊路追蹤系統支援的分析計算場景主要包括:

  • 拓撲計算:為每個微服務(精确到接口/叢集/機房粒度)計算上下遊依賴鍊路拓撲骨架,滿足業務架構梳理,全鍊路監控等場景需求。
  • 流量估算:聚合計算所有 Trace 并結合每條 Trace 的采樣率估算對外連結路的原始流量及調用比例,滿足活動擴容評估,流量來源分析,成本分攤計算等場景需求。
  • 錯誤鍊分析:聚合計算含有錯誤的 Trace 的錯誤傳播路徑,滿足故障根因定位,錯誤影響面分析,易故障點優化等場景需求。
  • 鍊路性能分析:聚合計算滿足特定條件的 Trace 并分析各環節的耗時及調用比例等資料,滿足全鍊路性能優化,耗時增加根因定位等場景需求。

不同的需求場景可以選擇不同的計算模式,目前位元組鍊路追蹤系統采用的計算模式主要有三種:

  • 近實時流式計算:從消息隊列中消費資料按照時間視窗進行流式聚合計算,近實時地不斷更新計算結果。例如拓撲計算主要采取此模式,以擷取近實時的拓撲骨架。
  • 即興抽樣計算:即興從線上存儲中按照特定條件抽樣檢索出有限數目(例如數百條)的 Trace 進行聚合計算,快速獲得計算結果。
  • 離線批計算:定時對離線數倉中的 Trace 進行 MapReduce 批計算,輸出分析結果。

大部分場景的的 Trace 分析計算實質都是批量 Trace 的 MapReduce 計算,基礎邏輯算子在不同的計算模式中可以複用。例如錯誤傳播鍊分析計算,既可以在故障時刻進行即興抽樣計算快速得到分析結果,也可以通過離線批計算的方式進行長期訂閱用于 SLO 持續優化。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

4)現階段實施效果

  • 吞吐量:Transaction 數 10 Million/秒(預設采樣率 0.1%),索引數 300 Million/秒
  • 查詢性能:TraceID 檢索性能 P50 < 100 毫秒, P99 < 500 毫秒
  • 資料産生到可檢索整體時延: AVG ≈ 1 分鐘,P99 < 2 分鐘
  • 存儲資源:5 PB (2 副本 TTL 15 天)

五、實踐應用案例

1、P99 慢請求根因追查

基于 Metrics, Trace, 底層調用分析和容器資源監控進行毛刺慢請求根因的快速定位。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

2、全鍊路實時監控

支援從任一微服務節點發起拓撲查詢,實時觀測各節點的流量/延遲/錯誤率/資源使用率/告警/變更等,快速從全鍊路視角擷取整體狀态資訊,用于日常巡檢、故障排查或壓測觀測等場景。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

3、活動大促全鍊路容量預估

各業務線會經常搞些活動來促進使用者增長或留存,在準備這些活動時,容量估算是一個必備階段,過程一般如下:

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

位元組鍊路追蹤系統可以根據入口在曆史時段上的 QPS,各節點調用比例,資源使用率等名額自動完成全鍊路各環節 QPS 增量與資源增量需求的一鍵估算。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

4、故障來源與影響面分析

當發生異常時,可以從線上存儲中快速批量檢索到異常 Trace 進行聚合計算,分析錯誤根源來自哪裡,傳播到了哪裡,影響到了哪些服務,并和昨日同時段錯誤率進行對比,幫助工程師在遇到故障時快速定位根因。錯誤傳播鍊計算也支援通過離線訂閱的方式,對全時段所有異常 Trace 進行長期計算,以助力于 SLO 長期優化。

位元組的分布式鍊路追蹤實踐,教科書式的搭建指南

小結

Trace 是軟體系統監控資料的連結紐帶,建立 Metrics/Trace/Log 的可靠關聯關系,是建構強大的可觀測性能力的基礎,基于優質的監控資料,可以回答監控排障,SLO 調優,架構梳理,流量估算,智能化故障歸因等衆多複雜問題。

位元組跳動在發展過程中,逐漸形成了十分複雜的超大規模微服務體系,我們面臨着很多挑戰,包括線上流量巨大,微服務數量巨大,疊代變化快,研發團隊龐大,分工複雜等,但同時也有着難得的機遇,即全公司層面的微服務基礎設施十分統一。

面對這樣的現狀,位元組鍊路追蹤系統圍繞着一些目标展開建設,這些目标有一些是項目建設之初就明确的,也有一些是在實踐過程中反思總結的,主要包括統一資料模型與語義,開放自定義,中心化配置管控,一站式觀測平台;業務內建開銷最小化,平衡存儲效率與檢索需求,多機房容災完備性和最小化架構與依賴複雜度。

接下來分享了位元組鍊路追蹤系統的整體實作。資料采集側的建設主要關注資料模型,語義統一,采樣政策以及熔斷保護等,并實作中心化配置管控。服務端的建設主要關注平衡成本和延遲,兼顧線上檢索和分析計算,保障多機房的容災完備性。

最後分享了位元組鍊路追蹤系統的一些實踐應用,例如 P99 慢請求根因追查,全鍊路實時監控,活動大促全鍊路容量預估和錯誤傳播分析等。

作者丨智能運維團隊

來源丨公衆号:位元組跳動技術團隊(ID:BytedanceTechBlog)

dbaplus社群歡迎廣大技術人員投稿,投稿郵箱:[email protected]

關注公衆号【dbaplus社群】,擷取更多原創技術文章和精選工具下載下傳

繼續閱讀