分布式鏈路追蹤實踐(一) - 分布式鏈路追蹤方案對比

分布式鏈路追蹤(全鏈路追蹤)是分布式系統(tǒng)或者微服務(wù)架構(gòu)中服務(wù)監(jiān)控、性能優(yōu)化的有效手段。分布式鏈路追蹤有 Jaeger, Zipkin, SkyWalking 等方案,我們詳細講解它們的架構(gòu)原理;

  • 分布式鏈路追蹤方案選型
  • 分布式鏈路追蹤實踐
  • 分布式鏈路追蹤 SDK

?向 DevOps 的診斷與分析系統(tǒng)

  • Logging - 集中式?志系統(tǒng): ?于記錄離散的事件。例如,應(yīng)?程序的調(diào)試信息或錯誤信息。它是我們診斷問題的依據(jù)。
  • Tracing - 分布式追蹤系統(tǒng): ?于記錄請求范圍內(nèi)的信息。例如,?次遠程?法調(diào)?的執(zhí)?過程和耗時。它是我們排查系統(tǒng)性能問題的利器。
  • Metrics - 集中式度量系統(tǒng): ?于記錄可聚合據(jù)。的數(shù)例如,隊列的當前深度可被定義為?個度量值,在元素?隊或出隊時被更新;HTTP 請求個數(shù)可被定義為?個計數(shù)器,新請求到來時進?累加。

所以 Logging,Metrics 和 Tracing 有各?專注的部分。

ltm.png

全鏈路 - 分布式追蹤

方案對比:

project.png
  • Drapper:google的Drapper--未開源,最早的APM

  • CAT:?眾點評跨服務(wù)的跟蹤功能與點評內(nèi)部的RPC框架集成,這部分未開源且項?在2014.1已經(jīng)停?維護。服務(wù)粒度的監(jiān)控,通過代碼埋點的?式來實現(xiàn)監(jiān)控,?如: 攔截器,注解,過濾器等,對代碼的侵?性較?,集成成本較?。

  • Hydra:京東Hydra與dubbo框架集成,對于服務(wù)級別的跟蹤統(tǒng)計,現(xiàn)有業(yè)務(wù)可以?縫接?。對于細粒度的興趣點,需要業(yè)務(wù)?員?動添加.開源項?已于2013年6?停?維護

  • PinPoint-naver:字節(jié)碼探針技術(shù),代碼?侵?,體系完善不易修改,?持java,技術(shù)棧?持dubbo.其他語?社區(qū)?援中

  • Zipkin:java?便集成于springcloud,社區(qū)?持的插件也包括dubbo,rabbit,mysql,httpclient等(https://github.com/openzipkin/brave/tree/master/instrumentation),同時?持php,go,js等語?客戶端,界?功能較為簡單,本身?告警功能,可能需要?次開發(fā)。代碼?侵度?。

  • Jaeger:Uber-Jaeger?持java/c++/go/node/php,在界?上較為完善(對?zipkin),但是也?告警功能。代碼?侵度?。dubbo?前?插件?持,可?次開發(fā)。

  • Skywalking:華為開源,類似于PinPoint,?前還在apache孵化中,?上吞吐量對?中強于pinpoint (實際未驗證), 本身?持dubbo

Jaeger

架構(gòu)設(shè)計

Jaeger是Uber開發(fā)的?套分布式追蹤系統(tǒng),受啟發(fā)于 dapper 和OpenZipkin,兼容 OpenTracing 標準,CNCF的開源項?。

Jaeger 架構(gòu)設(shè)計:

jaeger.png
  • Jaeger Client - 為不同語?實現(xiàn)了符合 OpenTracing 標準的 SDK。應(yīng)?程序通過 API 寫?數(shù)據(jù),client library 把 trace 信息按照應(yīng)?程序指定的采樣策略傳遞給 jaeger-agent。

  • Agent - 是?個監(jiān)聽在 UDP 端?上接收 span 數(shù)據(jù)的?絡(luò)守護進程,它會將數(shù)據(jù)批量發(fā)送給 collector。它被設(shè)計成?個基礎(chǔ)組件,推薦部署到所有的宿主機上。Agent 將 client library 和 collector 解耦,為 client library 屏蔽了路由和發(fā)現(xiàn) collector 的細節(jié)。

  • Collector - 接收 jaeger-agent 發(fā)送來的數(shù)據(jù),然后將數(shù)據(jù)寫?后端存儲。Collector 被設(shè)計成?狀態(tài)的組件,因此您可以同時運?任意數(shù)量的 jaeger-collector。

  • Data Store - 后端存儲被設(shè)計成?個可插拔的組件,?持將數(shù)據(jù)寫? cassandra、elastic search。

  • Query - 接收查詢請求,然后從后端存儲系統(tǒng)中檢索 trace 并通過 UI 進?展示。Query 是?狀態(tài)的,您可以啟動多個實例,把它們部署在 nginx 這樣的負載均衡器后?。

Agent 初始化類圖

TUDPTransport:基于Thrift框架的UDP傳輸類。
TBufferedServer:基于TUDPTransport的UDP服務(wù)器類。
Processor:消息處理類,提供Serve和Stop兩個接?。
ThriftProcessor:消息傳遞類,?于異步的將從UDPServer
這邊接收到的span消息,送?AgentProcessor處理。
AgentProcessor:根據(jù)協(xié)議區(qū)分jaeger和zipkin消息,接收
并處理method為emitBatch的消息,發(fā)送?Reporter。
HTTPServerConfiguration:?于配置HTTPServer。
HTTPServer?于接收Collector的HTTP配置消息,配置采樣
率等信息

jaeger_agent.png

Agent初始化序列圖

  • CreateReporter:app/builder.go 中提供createMainReporter接?,在接?中調(diào)?Builder.CreateReporter接?。CreateReporter接?在 app/report/tchannel/builder.go中實現(xiàn)。CreateReporter接?中創(chuàng)建了?個tchannel類型的Reporter。

  • NewAgentProcessor:根據(jù)zipkin和jaeger兩種協(xié)議類型,agent會創(chuàng)建各?的AgentProcessor。Jaeger類型的AgentProcessor實現(xiàn)在 thrift-gen/agent/agent.go。得到傳回的對象后作為handler傳? ThriftProcessor。

  • getUDPServer:創(chuàng)建基于 thrift 的 UDP 服務(wù)器,并作為?參傳? ThriftProcessor。

  • GetHTTPServer:創(chuàng)建基于HTTP的服務(wù)器,?于處理 Collector下發(fā)的配置,設(shè)置采樣率等信息。

jaeger_agent_ sequence.png

Agent數(shù)據(jù)流序列圖

  • Serve:Agent為不同協(xié)議的ThriftProcessor創(chuàng)建多個協(xié)程,并調(diào)?其Serve接?。

  • processBuffer:在ThriftProcessor的Serve接?中根據(jù)配置創(chuàng)建多個協(xié)程?于并發(fā)處理span消息。

  • DataRecd:TBufferedServer在Buffer池的機制,避免了空間反復的 new 和 delete。此處將?完的數(shù)據(jù)包返回TBufferedServer,以便下次接收數(shù)據(jù)時再次使?。

  • Process:ThriftProcessor將接收到的數(shù)據(jù)轉(zhuǎn)換成對應(yīng)的協(xié)議格式后,傳遞到AgentProcessor中。

  • Process:AgentProcessor 解析消息 Method 頭,如果為 EmitBatch 則調(diào)?對應(yīng)回調(diào)進?處理。當前只?持EmitBatch消息。

綜上所述,可以看出來Agent模塊主要通過tchannel接收本機的UDP消息(實為span消息),再傳遞?thrift框架的Reporter,發(fā)送?Collector。在Agent消息處理過程中,都為?進制協(xié)議消息,?明?。Agent不對消息內(nèi)容做任何修改。

jaeger_agent_data_sequence.png

SkyWalking

SkyWalking 架構(gòu)設(shè)計

SkyWalking 的核?是數(shù)據(jù)分析和度量結(jié)果的存儲平臺,通過 HTTP 或 gRPC ?式向SkyWalking Collecter 提交分析和度量數(shù)據(jù),SkyWalking Collecter 對數(shù)據(jù)進?分析和聚合,存儲到 Elasticsearch、H2、MySQL、TiDB 等其?即可,最后我們可以通過 SkyWalking UI 的可視化界?對最終的結(jié)果進?查看。SkyWalking ?持從多個來源和多種格式收集數(shù)據(jù):多種語?的 Skywalking Agent 、Zipkin v1/v2 、Istio 勘測、Envoy 度量等數(shù)據(jù)格式。

skywalking.png
  • SkyWalking 是針對分布式系統(tǒng)的 APM 系統(tǒng),也被稱為分布式追蹤系統(tǒng)全?動探針監(jiān)控,不需要修改應(yīng)?程序代碼。(查看?持的中間件和組件庫列表:https://github.com/apache/incubator/skywalking )
  • ?持?動探針監(jiān)控, 提供了?持 OpenTracing 標準的SDK。覆蓋范圍擴?到 OpenTracing-Java ?持的組件。 (查看OpenTracing組件?持表:https://github.com/opentracing-contrib/meta )
  • ?動監(jiān)控和?動監(jiān)控可以同時使?,使??動監(jiān)控彌補?動監(jiān)控不?持的組件,甚?私有化組件。純 Java 后端分析程序,提供 RESTful 服務(wù),可為其他語?探針提供分析能?。?性能純流式分析。
skywalking_arch2.png

SkyWalking 邏輯上分為四部分: 探針, 平臺后端, 存儲和?戶界?。

  • 探針:基于不同的來源可能是不?樣的, 但作?都是收集數(shù)據(jù), 將數(shù)據(jù)格式化為 SkyWalking 適?的格式

  • 平臺后端:是?個?持集群模式運?的后臺, ?于數(shù)據(jù)聚合, 數(shù)據(jù)分析以及驅(qū)動數(shù)據(jù)流從探針到?戶界?的流程. 平臺后端還提供了各種可插拔的能?, 如不同來源數(shù)據(jù)(如來? Zipkin)格式化, 不同存儲系統(tǒng)以及集群管理. 你甚?還可以使?觀測分析語?來進??定義聚合分析

  • 存儲:是開放式的. 你可以選擇?個既有的存儲系統(tǒng), 如 ElasticSearch, H2 或 MySQL 集群
    (Sharding-Sphere 管理), 也可以選擇??實現(xiàn)?個存儲系統(tǒng). 當然, 我們?常歡迎你貢獻新的存儲系統(tǒng)實現(xiàn)

  • ?戶界?:對于 SkyWalking 的最終?戶來說?常炫酷且強?. 同樣它也是可定制以匹配你已存在的后端的

探針限制

進程內(nèi)傳播在?多數(shù)情況下成為可能。許多?級編程語?(如 Java, .NET)都是?于構(gòu)建業(yè)務(wù)系統(tǒng). ?部分業(yè)務(wù)邏輯代碼對于每?個請求來說都運?在同?個線程內(nèi), 這使得傳播是基于線程 ID 的, 以確保上下?是安全的.僅僅對某些框架和庫奏效。因為是代理來在運?時修改代碼的, 這也意味著代理插件開發(fā)者事先就要知道 所要修改的代碼是怎么樣的. 因此, 在這種探針下通常會有?個已?持的列表清單.?持服務(wù)列表: https://github.com/apache/skywalking/blob/master/docs/en/setup/service-agent/java-agent/Supported-list.md

跨線程可能并?總是奏效 如上所述, 每個請求的代碼?都運?在?個線程之內(nèi), 對于業(yè)務(wù)代碼來說尤其如此. 但是在其他?些場景下, 它們也會在不同線程下?作, ?如指派任務(wù)到其他線程, 任務(wù)池, 以及批處理. 對于?些語?, 可能還提供了協(xié)程或類似的概念如 Goroutine, 使得開發(fā)者可以低開銷地來執(zhí)?異步操作, 在這些場景下, ?動打點可能會遇到?些問題。

動態(tài)探針技術(shù)

字節(jié)碼增加技術(shù)(有的叫動態(tài)探針技術(shù))來實現(xiàn)?侵?式的調(diào)?鏈采集。其核?實現(xiàn)原來還是基于JVM的javaagent機制來實現(xiàn):
"-javaagent:$AGENT_PATH/-bootstrap-$VERSION.jar "
來指定skywalking agent加載路徑,在啟動的時候agent將在加載應(yīng)?class?件之前做攔截并修改字節(jié)碼,在class?法調(diào)?的前后加上鏈路采集邏輯,從?實現(xiàn)鏈路采集功能。
javaAgent的底層機制主要依賴JVMTI ,JVMTI全稱JVM Tool Interface,是JVM暴露出來的?些供?戶擴展的接?集合。JVMTI是基于事件驅(qū)動的,JVM每執(zhí)?到?定的邏輯就會調(diào)??些事件的回調(diào)接?(如果有的話),這些接?可以供開發(fā)者擴展??的邏輯。但JVMTI都是?些接?合集,需要有接?的實現(xiàn),這就?到了java的instrument,可以理解instrument是JVMTI的?種實現(xiàn),為JVM提供外掛?持。

javaagent具體實現(xiàn)

使?:java -javaagent:myagent.jar=mode=test Test
javaagent 的主要功能如下:
? 可以在加載 class ?件之前做攔截,對字節(jié)碼做修改
? 可以在運?期對已加載類的字節(jié)碼做變更,但是這種情況下會有很多的限制,后?會詳細說
? 還有其他?些?眾的功能

?獲取所有已經(jīng)加載過的類
?獲取所有已經(jīng)初始化過的類(執(zhí)?過 clinit ?法,是上?的?個?集)
?獲取某個對象的??
?將某個 jar 加?到 bootstrap classpath ?作為?優(yōu)先級被 bootstrapClassloader 加載
?將某個 jar 加?到 classpath ?供 AppClassloard 去加載
?設(shè)置某些 native ?法的前綴,主要在查找 native ?法的時候做規(guī)則匹配

JVMTI 全稱 JVM Tool Interface,是 JVM 暴露出來的?些供?戶擴展的接?集合。JVMTI 是基于事件驅(qū)動的,JVM 每執(zhí)?到?定的邏輯就會調(diào)
??些事件的回調(diào)接?(如果有的話),這些接?可以供開發(fā)者擴展??的邏輯。?如最常?的,我們想在某個類的字節(jié)碼?件讀取之后、類
定義之前修改相關(guān)的字節(jié)碼,從?使創(chuàng)建的 class 對象是我們修改之后的字節(jié)碼內(nèi)容,那就可以實現(xiàn)?個回調(diào)函數(shù)賦給 jvmtiEnv(JVMTI 的運
?時,通常?個 JVMTIAgent 對應(yīng)?個 jvmtiEnv,但是也可以對應(yīng)多個)的回調(diào)?法集合?的 ClassFileLoadHook,這樣在接下來的類?件加
載過程中都會調(diào)?到這個函數(shù)中。

instrument agent

instrument agent 實現(xiàn)了Agent_OnLoad和Agent_OnAttach兩?法,也就是說在使?時,agent既可以在啟動時加載,也可以在運?時動態(tài)加
載。其中啟動時加載還可以通過類似-javaagent:myagent.jar的?式來間接加載 instrument agent,運?時動態(tài)加載依賴的是 JVM 的 attach 機制
( JVM Attach 機制實現(xiàn)),通過發(fā)送 load 命令來加載 agent。

skywalking_agent_structure.png

在啟動時加載 instrument agent
啟動時加載 instrument agent,具體過程都在InvocationAdapter.cAgent_OnLoad?法?,這?簡單描述下過程:
創(chuàng)建并初始化 JPLISAgent
監(jiān)聽 VMInit 事件,在 vm 初始化完成之后做下?的事情:
創(chuàng)建 InstrumentationImpl 對象
監(jiān)聽 ClassFileLoadHook 事件
調(diào)? InstrumentationImpl 的loadClassAndCallPremain?法,在這個?法?會調(diào)? javaage
在運?時加載 instrument agent
上?會通過 JVM 的 attach 機制來請求?標 JVM 加載對應(yīng)的 agent,過程?致如下:
創(chuàng)建并初始化 JPLISAgent
解析 javaagent ? MANIFEST.MF ?的參數(shù)
創(chuàng)建 InstrumentationImpl 對象
監(jiān)聽 ClassFileLoadHook 事件
調(diào)? InstrumentationImpl 的loadClassAndCallAgentmain?法,在這個?法?會調(diào)? javaagent ? MANIFEST.MF ?指定的Agent-Class類的
agentmain?法

skywalking_ui.png

Zipkin

Zipkin 組件設(shè)計

Zipkin是?個分布式追蹤系統(tǒng)。它有助于收集解決微服務(wù)架構(gòu)中延遲
問題所需的時序數(shù)據(jù)。它管理這些數(shù)據(jù)的收集和查找。Zipkin的設(shè)計
基于 Google Dapper論?。
共有四個組件構(gòu)成了 Zipkin:

  • collector
  • storage
  • search
  • web UI
    Reporter是裝配應(yīng)?中?于向 Zipkin 發(fā)送數(shù)據(jù)的組件。Reporter 通過
    Transport 發(fā)送追蹤數(shù)據(jù)到 Zipkin 的 Collector,Collector 持久化數(shù)據(jù)
    到 Storage 中。之后,API 從 Storage 中查詢數(shù)據(jù)提供給 UI。
zipkin_arch.png

Zipkin 架構(gòu)設(shè)計

  • Transport:
    裝配庫發(fā)送的跨度必須由裝配的服務(wù)傳輸?shù)?Collector。 有三種主要的傳輸類型:
    HTTP、Scribe 和 Kafka。更多信息查看跨度接收器。

  • Collector:
    ?旦追蹤數(shù)據(jù)抵達 Zipkin Collector 守護進程,Zipkin Collector 為了查詢,會對其進
    ?校驗、存儲和索引。

  • Storage:
    Zipkin 最初是構(gòu)建在將數(shù)據(jù)存儲在 Cassandra 中,因為 Cassandra 易跨站,?持
    靈活的 schema,并且在 Twitter 內(nèi)部被?規(guī)模使?。然?,我們將這個組件做成了
    可插拔式的。在 Cassandra 之外,我們原??持 ElasticSearch 和 MySQL??勺鳛?br> 第三?擴展提供給其它后端。

Zipkin 查詢服務(wù):

?旦數(shù)據(jù)被存儲索引,我們就需要?種?式提取它。查詢守護進程提供了?個簡單
的 JSON API 查詢和獲取追蹤數(shù)據(jù)。API 的主要消費者就是 Web UI。

Web UI:

我們創(chuàng)建了?個?戶圖形界?為追蹤數(shù)據(jù)提供了?個漂亮的視圖。Web UI 提供了基
于服務(wù)、時間和標記(annotation)查看追中數(shù)據(jù)的?法。注意:UI 沒有內(nèi)置的身
份認證功能。

zipkin_arch2.png
zipkin_community_support.png
zipkin_ui.png

總結(jié)

  1. 非侵入性,并且對 JAVA, .NET 等語言支持,可以選擇 SkyWalking, 接入成本較小 ;
  2. 如果采用 OpenTracing 集成接入,可以選擇 Jaeger 或者 Zipkin ,侵入性比較大,接入成本中等;
  3. Service Mesh Tracing 接入 (如 istio tracing ),侵入性較小,接入成本較小 ;

在生產(chǎn)中使用,需要看團隊研發(fā)力量和需求,1-3 種方案均可以實施。
下一章和大家分享 自研 分布式鏈路追蹤 SDK 。

原文: 分布式鏈路追蹤實踐(一)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容