SOFA Scalable Open Financial Architecture 是螞蟻金服自主研發的金融級分佈式中間件,包含了構建金融級雲原生架構所需的各個組件,是在金融場景裏錘鍊出來的最佳實踐。
SOFATracer 是一個用於分佈式系統調用跟蹤的組件,經過統一的 TraceId 將調用鏈路中的各類網絡調用狀況以日誌的方式記錄下來,以達到透視化網絡調用的目的,這些鏈路數據可用於故障的快速發現,服務治理等。 SOFAT racer :https://github.com/alipay/sofa-tracer
本文爲《剖析 | SOFATracer 框架》第一篇。《剖析 | SOFASOFATracer 框架》系列由 SOFA 團隊和源碼愛好者們出品, 項目代號:<SOFA:TracerLab/>,文章尾部有參與方式,歡迎一樣對源碼熱情的你加入html
在單體應用時代,咱們不須要花費時間去關心調用鏈路這個東西。可是鏈路跟蹤不只僅是在分佈式場景下才會有,即便是單體應用,一樣也會存在調用鏈路。例如,咱們把應用中的每一個服務接口做爲一個鏈路節點,那麼從請求進來到返回響應,把這個過程當中多歷經的全部的方法接口串聯起來,就能組成一條完整的鏈路,以下圖所示:git
SOFATracer
分佈式鏈路跟蹤組件,爲實施大規模服務化體系架構場景下提供了鏈路跟蹤的解決方案。
SOFATracer
以前,先來了解一下
Opentracing
規範。
首先來解釋下 OpenTracing
是什麼 OpenTracing
致力於爲分佈式跟蹤建立更標準化的API和工具,它由完整的API規範、實現該規範的框架、庫以及項目文檔組成。github
OpenTracing
提供了一套平臺無關、廠商無關的
API
,這樣不一樣的組織或者開發人員就可以更加方便的添加或更換追蹤系統的實現。
OpenTracingAPI
中的一些概念和術語,在不一樣的語言環境下都是共享的。
Opentracing
規範中,一條
trace
鏈路是由多個與之關聯的
span
組成,一條鏈路總體能夠看作是一張有向無環圖,各個
span
之間的邊緣關係被稱之爲「
References
」。下面是官方提供的示例:
可是爲了簡化root span
: 當前鏈路中的第一個span
ChildOf
和FollowFrom
是目前被定義的兩種References
類型ChildOf
: 父級 span某種程度上取決於子span (子span的結果可能會對父span產生影響)
FollowFrom
: 父Span
不以任何方式依賴子Span
span
之間的這種依賴關係,在具體實現時一般會將具備嵌套關係的做爲
ChildOf
,平行執行的做爲
FollowFrom
,好比:
methodA
中調用了
method
B :
span
在時間維度上展示的視角以下:
SpanBChildOfSpanA
。
method
方法中,
methodA
執行以後
methodB
執行 :
span
在時間維度上展示的視角以下:
SpanBFollowFromSpanA
。
OpentracingAPI
是對分佈式鏈路中涉及到的一些列操做的高度抽象集合。
Opentracing
中將全部核心的組件都聲明爲接口,例如
Tracer
、
Span
、
SpanContext
、
Format
(高版本中還包括
Scope
和
ScopeManager
)等。
SOFATracer
使用的版本是 0.22.0 ,主要是對
Tracer
、
Span
、
SpanContext
三個概念模型的實現。下面就針對這三個組件結合
SOFATracer
來分析。
SOFATracer
中對於這三個核心接口實現的類圖結構:
a、Tracer & SofaTracer因爲篇幅緣由,下面的介紹過程當中一些點不會展開說明,有興趣的同窗能夠自行官網查看完整的 OpenTracing-api 規範 (opentracing.io/specificati…)。web
Tracer
是一個簡單、廣義的接口,它的做用就是構建
span
和傳輸
span
。核心接口列表以下:
接口 | 描述 |
---|---|
SpanBuilder buildSpan(String operationName) | 根據指定的operationName構建一個新的span |
void inject(SpanContext spanContext, Formatformat, C carrier); | 將 spanContext 以 format 的格式注入到 carrier 中 |
SpanContext extract(Format format, C carrier); | 以 format 的格式從carrier中解析出 SpanContext |
SofaTracer
實現了
Tracer
接口,並擴展了採樣、數據上報等能力。
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
類型等處理的能力。
SpanContext
對於
OpenTracing
實現是相當重要的,經過
SpanContext
能夠實現跨進程的鏈路透傳,而且能夠經過
SpanContext
中攜帶的信息將整個鏈路串聯起來。
官方文檔中有這樣一句話:「在
OpenTracing
中,咱們強迫SpanContext
實例成爲不可變的,以免Span
在finish
和reference
操做時會有複雜的生命週期問題。」 這裏是能夠理解的,若是SpanContext
在透傳過程當中發生了變化,好比改了tracerId
,那麼就可能致使鏈路出現斷缺。api
SpanContext
中只有一個接口:
接口 | 描述 |
---|---|
Iterable> baggageItems(); | 拿到全部的baggageItems 透傳數據 |
SofaTracerSpanContext
實現了
SpanContext
接口,擴展了構建
SpanContext
、序列化
baggageItems
以及
SpanContext
等新的能力,除此以外,
SpanContext
在跨進行透傳時攜帶的信息進行了規範:
攜帶信息 | 描述 |
---|---|
traceId | 全鏈路惟一的標識信息 |
spanId | spanId |
parentId | 父 spanId |
isSampled | 採樣標記 |
sysBaggage | 系統透傳數據 |
bizBaggage | 業務透傳數據 |
爲了知足在複雜場景下的鏈路跟蹤需求, SOFATracer
在 Opentracing
規範基礎上又提供了豐富的擴展能力。網絡
SOFATracer
基於
OpenTracing 規範
(
opentracing.io/specificati…
)實現,而且經過
Disruptor
(
github.com/LMAX-Exchan…
)組件實現了日誌的無鎖異步打印能力。
基於 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
自己來管控,對於不一樣的組件能夠輕鬆的實現差別化和定製化。
OpentracingAPI
的埋點擴展實現,從而實現與
opentracing-contrib
的無縫對接。基於
OpentracingAPI
的插件埋點方案以下圖所示:
SOFATracer
基於特有
API
埋點的實現以及如何實現對接
OT-api
埋點,期待你們一塊兒編寫,領取方式見文末。
SOFATracer
的數據上報機制
SOFATracer
中並無將不一樣的
Reporter
設計成不一樣的策略,而後根據不一樣的策略來實現具體的上報操做,而是使用了一種相似組合的方式,而且在執行具體上報的流程中經過參數來調控是否執行具體的上報。
zipkin
,後面是落盤;在日誌記錄方面,
SOFATracer
中爲不一樣的組件均提供了獨立的日誌空間,除此以外,
SOFATracer
在鏈路數據採集時提供了兩種不一樣的日誌記錄模式:摘要日誌和統計日誌,這對於後續構建一些如故障的快速發現、服務治理等管控端提供了強大的數據支撐。關於數據上報,期待你們一塊兒編寫,領取方式見文末。
對於鏈路中的數據,並不是全部的數據都是值得關注的。一方面是能夠節約磁盤空間,另外一方面能夠將某些無關數據直接過濾掉。基於此,SOFATracer
的採樣機制
SOFATracer
提供了鏈路數據採樣能力。目前咱們提供了兩種策略,一種是基於固定比率的採樣,另外一種是基於用戶擴展實現的自定義採樣;在自定義採樣設計中,咱們將
SofaTracerSpan
實例做爲採樣計算的條件,用戶能夠基於此實現豐富的採樣規則。關於採樣機制,期待你們一塊兒編寫,領取方式見文末。
關於透傳機制,咱們不只須要考慮線程內傳遞,還須要考慮跨線程以及異步線程場景,對於分佈式鏈路來講,最核心還有如何實現跨進程的數據透傳。關於SOFATracer
鏈路透傳機制
SOFATracer
鏈路透傳 以及
OpenTracing
新規範中對線程傳遞的支持,期待你們一塊兒編寫,領取方式見文末。
SOFATracer
的現狀和一些正在作的事情。
SOFATracer
版本說明:
3.x 版本支持歡迎對相關功能和webflux
等,基於分支發佈。
2.x 版本基於master
發佈,目前版本是 2.3.0 。
feature
有興趣的同窗,一塊兒參與開發~
本文做爲《剖析 | SOFATracer
組件系列》第一篇,主要仍是但願你們對 SOFATracer
組件有一個認識和了解,以後,咱們會逐步詳細介紹每部分的代碼設計和實現,預計會按照以下的目錄進行:架構
SOFATracer
概述【已完成】SOFATracer
數據上報機制和源碼分析【待領取】SOFATracerAPI
組件埋點機制和源碼分析【待領取】SOFATracer
鏈路透傳原理與 SLF4J MDC
的擴展能力分析【待領取】SOFATracer
的採樣策略和源碼分析【待領取】SOFA
,關注
SOFATracer
,咱們會一直與你們一塊兒成長的。
除了源碼解析,也歡迎提交 issue 和 PR: SOFATracer:https://github.com/alipay/sofa-tracer框架
長按關注,獲取分佈式架構乾貨異步
歡迎你們共同打造 SOFAStack https://github.com/alipay