螞蟻金服分散式鏈路跟蹤元件 SOFATracer 總覽 | 剖析
SOFA
Scalable Open Financial Architecture
是螞蟻金服自主研發的金融級分散式中介軟體,包含了構建金融級雲原生架構所需的各個元件,是在金融場景裡錘鍊出來的最佳實踐。
SOFATracer 是一個用於分散式系統呼叫跟蹤的元件,通過統一的 TraceId 將呼叫鏈路中的各種網路呼叫情況以日誌的方式記錄下來,以達到透視化網路呼叫的目的,這些鏈路資料可用於故障的快速發現,服務治理等。
本文為《剖析 | SOFATracer 框架》第一篇。《剖析 | SOFATracer 框架》系列由 SOFA 團隊和原始碼愛好者們出品,專案代號:<SOFA:TracerLab/>,
文章尾部有參與方式,歡迎同樣對原始碼熱情的你加入。
0. 前言
在單體應用時代,我們不需要花費時間去關心呼叫鏈路這個東西。
但是鏈路跟蹤不僅僅是在分散式場景下才會有,即使是單體應用,同樣也會存在呼叫鏈路。
例如,我們把應用中的每個服務介面作為一個鏈路節點,那麼從請求進來到返回響應,把這個過程中多歷經的所有的方法介面串聯起來,就能組成一條完整的鏈路,如下圖所示:
對於單體應用而言,如果訪問一個資源沒有成功,那麼我們可以很快的鎖定是哪一臺機器,然後通過查詢這臺機器上的日誌就能定位問題。
但是在微服務體系架構下,這種方式會顯得非常無力。對於一個稍具規模的應用來說,一次請求可能會跨越相當多的服務節點,在這種情況下,如果一個請求沒有得到成功的響應,就不能確定到底是哪個節點出了問題。
因此在面對這種複雜的大規模分散式叢集來實現的服務體系來說,就需要一些可以幫助理解各個應用的線上呼叫行為、並可以分析遠端呼叫的元件。
基於上述背景,螞蟻金服開源了基於 OpenTracing 規範(http://opentracing.io/documentation/pages/spec.html)實現的 SOFATracer
分散式鏈路跟蹤元件,為實施大規模服務化體系架構場景下提供了鏈路跟蹤的解決方案。
在介紹 SOFATracer
之前,先來了解一下 Opentracing
規範。
1. Opentracing 簡介
首先來解釋下 OpenTracing
是什麼OpenTracing
OpenTracing
提供了一套平臺無關、廠商無關的 API
,這樣不同的組織或者開發人員就能夠更加方便的新增或更換追蹤系統的實現。 OpenTracing API
中的一些概念和術語,在不同的語言環境下都是共享的。
1.1 資料模型
Opentracing
規範中,一條 trace
鏈路是由多個與之關聯的 span
組成,一條鏈路整體可以看做是一張有向無環圖,各個span
之間的邊緣關係被稱之為“References
”。下面是官方提供的示例:
如果以時間軸維度來看的話,也可以表現為下面的形式(官方示例):
root span
: 當前鏈路中的第一個span
ChildOf
和FollowFrom
是目前被定義的兩種References
型別ChildOf
: 父Span
某種程度上取決於子Span
, (子Span
的結果可能會對父Span
產生影響)FollowFrom
: 父Span
不以任何方式依賴子Span
但是為了簡化 span
之間的這種依賴關係,在具體實現時通常會將具有巢狀關係的作為 ChildOf
,平行執行的作為FollowFrom
,比如:
a. ChildOf 示例
在 methodA
中呼叫了 method
B :
methodA(){ // spanA start
methodB();
} // spanA finish
methodB(){ // spanB start
} // spanB finish
複製程式碼
產生的 span
在時間維度上展現的視角如下:
這種關係一般會表示為 SpanB ChildOf SpanA
。
b. FollowFrom 示例
method
方法中,methodA
執行之後 methodB
執行 :
method(){
methodA();
methodB();
}
複製程式碼
產生的 span
在時間維度上展現的視角如下:
這種關係一般會表示為 SpanB FollowFrom SpanA
。
1.2 API
Opentracing API
是對分散式鏈路中涉及到的一些列操作的高度抽象集合。Opentracing
中將所有核心的元件都宣告為介面,例如 Tracer
、Span
、SpanContext
、Format
(高版本中還包括 Scope
和 ScopeManager
)等。SOFATracer
使用的版本是 0.22.0 ,主要是對 Tracer
、Span
、SpanContext
三個概念模型的實現。下面就針對這三個元件結合 SOFATracer
來分析。
1.3 SOFATracer 標準實現
下圖為 SOFATracer
中對於這三個核心介面實現的類圖結構:
由於篇幅原因,下面的介紹過程中一些點不會展開說明,有興趣的同學可以自行官網檢視完整的 OpenTracing-api 規範 (https://opentracing.io/specification/)。
a. Tracer & SOFATracer
Tracer
是一個簡單、廣義的介面,它的作用就是構建 span
和傳輸 span
。核心介面列表如下:
介面 |
描述 |
SpanBuilder buildSpan(String operationName) |
根據指定的operationName構建一個新的span |
<C> void inject(SpanContext spanContext, Format<C> format, C carrier); |
將 spanContext 以 format 的格式注入到 carrier 中 |
<C> SpanContext extract(Format<C> format, C carrier); |
以 format 的格式從carrier中解析出 SpanContext |
SofaTracer
實現了 Tracer
介面,並擴充套件了取樣、資料上報等能力。
b. Span & SOFATracerSpan
Span
是一個跨度單元,在實際的應用過程中,Span
就是一個完整的資料包,其包含的就是當前節點所需要上報的資料。核心介面列表如下:
介面 |
描述 |
SpanContext context() |
從 span 中獲取 SpanContext |
void finish()/void finish(long finishMicros) |
結束一個 span |
void close() |
關閉 span |
Span setTag(String key, value) |
設定 tags |
Span log(long timestampMicroseconds, String event) |
設定 log 事件 |
Span setOperationName(String operationName) |
設定span的operationName |
Span setBaggageItem(String key, String value) |
設定 BaggageItem |
String getBaggageItem(String key) |
獲取 BaggageItem |
關於tags
和log
的解釋:如果把從進入公司到離開公司這段時間作為一個span
,那麼tags
裡面可以是你寫的程式碼,你喝的水,甚至你講過的話;log
則更關注某個時刻的事,比如在12:00 去吃了個飯,在15:00 開了個會。如果說
tags
裡面都是和公司有關的,那麼Baggage
裡面則不僅僅是侷限於你在公司的事,比如你口袋裡的手機。
SofaTracerSpan
在實現 Span
介面,並擴充套件了對 Reference
、tags
、執行緒非同步處理以及外掛擴充套件中所必須的 logType
和產生當前 span
的 Tracer
型別等處理的能力。
c. SpanContext & SOFATracerSpanContext
SpanContext
對於 OpenTracing
實現是至關重要的,通過 SpanContext
可以實現跨程序的鏈路透傳,並且可以通過 SpanContext
中攜帶的資訊將整個鏈路串聯起來。
官方文件中有這樣一句話:“在
OpenTracing
中,我們強迫SpanContext
例項成為不可變的,以避免Span
在finish
和reference
操作時會有複雜的生命週期問題。” 這裡是可以理解的,如果SpanContext
在透傳過程中發生了變化,比如改了tracerId
,那麼就可能導致鏈路出現斷缺。
SpanContext
中只有一個介面:
介面 |
描述 |
Iterable<Map.Entry<String, String>> baggageItems(); |
拿到所有的baggageItems 透傳資料 |
SofaTracerSpanContext
實現了 SpanContext
介面,擴充套件了構建 SpanContext
、序列化 baggageItems
以及SpanContext
等新的能力,除此之外,SpanContext
在跨進行透傳時攜帶的資訊進行了規範:
攜帶資訊 |
描述 |
traceId |
全鏈路唯一的標識資訊 |
spanId |
spanId |
parentId |
父spanId |
isSampled |
取樣標記 |
sysBaggage |
系統透傳資料 |
bizBaggage |
業務透傳資料 |
2. SOFATracer 擴充套件
為了滿足在複雜場景下的鏈路跟蹤需求,SOFATracer
在 Opentracing
規範基礎上又提供了豐富的擴充套件能力。
2.1 SOFATracer 架構及功能擴充套件
SOFATracer
基於 OpenTracing 規範(https://opentracing.io/specification/)實現,並且通過 Disruptor (https://github.com/LMAX-Exchange/disruptor)元件實現了日誌的無鎖非同步列印能力。
基於 SLF4J 的 MDC 擴充套件能力
應用在通過面向日誌程式設計介面 SLF4J
列印應用日誌時,可以只在對應的日誌實現配置檔案的 PatternLayout
中新增相應的引數即可,如新增 [%X{SOFA-TraceId},%X{SOFA-SpanId}]
,那麼應用日誌就可以在發生鏈路呼叫時打印出相應的 TraceId
和 SpanId
,而無論應用具體的日誌實現是 Logback
、Log4j2
或者 Log4j
。關於這部分的實現原理,期待大家一起編寫,領取方式見文末。
SOFATracer
的埋點機制
SOFATracer
目前僅提供了基於自身 API
埋點的方式。SOFATracer
中所有的外掛均需要實現自己的 Tracer
例項,如 Mvc
的 SpringMvcTracer
、HttpClient
的 HttpClientTracer
等,如下圖所示:
SOFATracer
將不同的擴充套件元件分為 AbstractClientTracer
和 AbstractServerTracer
,再通過AbstractClientTracer
和 AbstractServerTracer
衍生出具體的元件 Tracer
實現。這種方式的好處在於,所有的外掛實現均有 SOFATracer
本身來管控,對於不同的元件可以輕鬆的實現差異化和定製化。
但是為了能夠擁抱社群,我們在後續的版本中將會提供基於 Opentracing API
的埋點擴充套件實現,從而實現與 opentracing-contrib 的無縫對接。基於 Opentracing API
的外掛埋點方案如下圖所示:
關於 SOFATracer
基於特有 API
埋點的實現以及如何實現對接 OT-api
埋點,期待大家一起編寫,領取方式見文末。
SOFATracer
的資料上報機制
SOFATracer
中並沒有將不同的 Reporter
設計成不同的策略,然後根據不同的策略來實現具體的上報操作,而是使用了一種類似組合的方式,並且在執行具體上報的流程中通過引數來調控是否執行具體的上報。
從流程圖中可以看到,此過程中涉及到了三個上報點,首先是上報到 zipkin
,後面是落盤;在日誌記錄方面,SOFATracer
中為不同的元件均提供了獨立的日誌空間,除此之外,SOFATracer
在鏈路資料採集時提供了兩種不同的日誌記錄模式:摘要日誌和統計日誌,這對於後續構建一些如故障的快速發現、服務治理等管控端提供了強大的資料支撐。關於資料上報,期待大家一起編寫,領取方式見文末。
SOFATracer
的取樣機制
對於鏈路中的資料,並非所有的資料都是值得關注的。一方面是可以節約磁碟空間,另一方面可以將某些無關資料直接過濾掉。基於此,SOFATracer
提供了鏈路資料取樣能力。目前我們提供了兩種策略,一種是基於固定比率的取樣,另一種是基於使用者擴充套件實現的自定義取樣;在自定義取樣設計中,我們將 SofaTracerSpan
例項作為取樣計算的條件,使用者可以基於此實現豐富的取樣規則。關於取樣機制,期待大家一起編寫,領取方式見文末。
SOFATracer
鏈路透傳機制
關於透傳機制,我們不僅需要考慮執行緒內傳遞,還需要考慮跨執行緒以及非同步執行緒場景,對於分散式鏈路來說,最核心還有如何實現跨程序的資料透傳。關於 SOFATracer
鏈路透傳 以及 OpenTracing
新規範中對執行緒傳遞的支援,期待大家一起編寫,領取方式見文末。
2.2 SOFATracer RoadMap
首先介紹下目前 SOFATracer
的現狀和一些正在做的事情。
SOFATracer
版本說明:
3.x 版本支援
webflux
等,基於分支釋出。2.x 版本基於
master
釋出,目前版本是 2.3.0 。
歡迎對相關功能和 feature
有興趣的同學,一起參與開發~
歡迎加入,參與 SOFATracer 原始碼解析
本文作為《剖析 | SOFATracer
元件系列》第一篇,主要還是希望大家對 SOFATracer
元件有一個認識和了解,之後,我們會逐步詳細介紹每部分的程式碼設計和實現,預計會按照如下的目錄進行:
分散式鏈路跟蹤元件
SOFATracer
概述【已完成】SOFATracer
資料上報機制和原始碼分析【待領取】SOFATracer API
元件埋點機制和原始碼分析【待領取】SOFATracer
鏈路透傳原理與SLF4J MDC
的擴充套件能力分析【待領取】SOFATracer
的取樣策略和原始碼分析【待領取】
如果有同學對以上某個主題特別感興趣的,可以留言討論,我們會適當根據大家的反饋調整文章的順序,謝謝大家關注 SOFA
,關注 SOFATracer
,我們會一直與大家一起成長的。
領取方式:
掃碼關注並回複本公眾號想認領的文章名稱,我們將會主動聯絡你,確認資質後,即可加入,It's your show time!
除了原始碼解析,也歡迎提交 issue 和 PR:
SOFATracer:https://github.com/alipay/sofa-tracer
長按關注,獲取分散式架構乾貨
歡迎大家共同打造 SOFAStack https://github.com/alipay