2019新春支付寶紅包技術大揭秘在線峰會將於03-07日開始,點擊這里報名屆時即可參與大牛互動。
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 致力於為分布式跟蹤創建更標准化的API和工具,它由完整的API規范、實現該規范的框架、庫以及項目文檔組成。
OpenTracing 提供了一套平台無關、廠商無關的 API,這樣不同的組織或者開發人員就能夠更加方便的添加或更換追蹤系統的實現。 OpenTracing API 中的一些概念和術語,在不同的語言環境下都是共享的。
1.1 數據模型
Opentracing 規范中,一條 trace 鏈路是由多個與之關聯的 span 組成,一條鏈路整體可以看做是一張有向無環圖,各個span之間的邊緣關系被稱之為“References”。下面是官方提供的示例:
如果以時間軸維度來看的話,也可以表現為下面的形式(官方示例):
- root span : 當前鏈路中的第一個 span
- ChildOf 和 FollowFrom 是目前被定義的兩種 References
類型 ChildOf : 父 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 。核心接口列表如下:
SofaTracer 實現了 Tracer 接口,並擴展了采樣、數據上報等能力。
b. Span & SOFATracerSpan
Span 是一個跨度單元,在實際的應用過程中,Span 就是一個完整的數據包,其包含的就是當前節點所需要上報的數據。核心接口列表如下:
關於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 中只有一個接口:
SofaTracerSpanContext 實現了 SpanContext 接口,擴展了構建 SpanContext、序列化 baggageItems 以及SpanContext等新的能力,除此之外,SpanContext 在跨進行透傳時攜帶的信息進行了規范:
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 。
點擊閱讀更多,查看更多詳情