SpringCloud 入門實戰(11)--Zipkin(1)--簡介


Zipkin 是一款開源的分布式實時數據追蹤系統,基於 Google Dapper 的論文設計而來,由 Twitter 公司開發貢獻;其主要功能是聚集來自各個異構系統的實時監控數據。本文主要介紹下 Zipkin 的基本概念。

1、Zipkin 結構

1.1、Zipkin 服務端

 Zipkin 服務端由四部分組成:

Collector:收集器組件,處理從外部系統發送過來的跟蹤信息,將這些信息轉換為 Zipkin 內部的 Span 格式,以支持后續的存儲、分析、展示等功能。
Storage:存儲組件,存儲收集器接收到的跟蹤信息,默認會將這些信息存儲在內存中;可以修改存儲策略,把跟蹤信息保存到 MySQL、cassandra、elasticsearch。
API:API組件,提供 API 接口供 UI 組件調用,外接系統訪問該 API 實現定制化的監控。
UI:UI組件,基於 API 組件實現的上層應用;通過 UI 可以方便直觀地查詢和分析跟蹤信息。

1.2、Zipkin 客戶端

Brave 是 Zipkin 提供的 Java 版本的信息采集插件;提供了面向 Standard Servlet、Spring MVC、Http Client、JAX RS、Jersey、Resteasy 和 MySQL 等框架的采集能力,可以通過簡單的配置和代碼,讓基於這些框架構建的應用向 Zipkin 報告數據。同時 Brave 也提供了非常簡單且標准化的接口,在以上封裝無法滿足要求的時候可以方便擴展與定制。Brave 主要是利用攔截器在請求前和請求后分別埋點。例如 Spingmvc 監控使用 Interceptors,Mysql 監控使用 statementInterceptors。同理 Dubbo 的監控是利用 com.alibaba.dubbo.rpc.Filter 來過濾生產者和消費者的請求。

當然 Zipkin 也提供 其他語言的客戶端:C#、Go、JavaScript、Ruby、Scala、PHP。

1.3、Transport

連接 Zipkin 服務端和客戶端的數據傳輸通道(Transport) 可以為:Http, Kafka, Scribe。

支持的客戶端及傳輸通道詳情可參考官網:https://zipkin.io/pages/tracers_instrumentation.html

2、Zipkin 傳播規范

當上游服務通過 HTTP 調用下游服務,如何將兩個服務中的所有 span 串聯起來,形成一個 trace,這就需要上游服務將 traceId 等信息傳遞給下游服務,而不能讓下游重新生成一個 traceId。Zipkin 通過 B3 傳播規范(B3 Propagation),將相關信息(如 traceId、spanId 等)通過 HTTP 請求 Header 傳遞給下游服務:

3、Zipkin 數據模型

[{
    "traceId": "8cafeeba762c479e",
    "parentId": "c149cb2af458c95d",
    "id": "b5809e988d9b47f8",
    "kind": "CLIENT",
    "name": "post",
    "timestamp": 1623828578382618,
    "duration": 848226,
    "localEndpoint": {"serviceName": "scdemo-client"},
    "remoteEndpoint": {"ipv4": "10.49.196.1", "port": 9001},
    "tags": {"http.method": "POST", "http.path": "/user/getUserServer"}
}, {
    "traceId": "8cafeeba762c479e",
    "parentId": "8cafeeba762c479e",
    "id": "c149cb2af458c95d",
    "kind": "CLIENT",
    "name": "post",
    "timestamp": 1623828578373868,
    "duration": 860200,
    "localEndpoint": {"serviceName": "scdemo-client"},
    "tags": {"http.method": "POST", "http.path": "/user/getUserServer"}
}, {
    "traceId": "8cafeeba762c479e",
    "id": "8cafeeba762c479e",
    "kind": "SERVER",
    "name": "get /user/getuser",
    "timestamp": 1623828578361068,
    "duration": 893538,
    "localEndpoint": {"serviceName": "scdemo-client"},
    "remoteEndpoint": {"ipv6": "::1", "port": 65247},
    "tags": {
        "http.method": "GET",
        "http.path": "/user/getUser",
        "mvc.controller.class": "UserController",
        "mvc.controller.method": "getUser"
    }
}, {
    "traceId": "8cafeeba762c479e",
    "parentId": "b5809e988d9b47f8",
    "id": "872ba1f271335796",
    "kind": "CLIENT",
    "name": "select",
    "timestamp": 1623828579160625,
    "duration": 16508,
    "localEndpoint": {"serviceName": "scdemo-server"},
    "remoteEndpoint": {"serviceName": "mydb", "ipv4": "10.40.94.232", "port": 3306},
    "tags": {"sql.query": "select now()"}
}, {
    "traceId": "8cafeeba762c479e",
    "parentId": "b5809e988d9b47f8",
    "id": "26f5a8fb4cfacdfc",
    "kind": "CLIENT",
    "name": "select",
    "timestamp": 1623828579198865,
    "duration": 5071,
    "localEndpoint": {"serviceName": "scdemo-server"},
    "remoteEndpoint": {"serviceName": "mydb", "ipv4": "10.40.94.232", "port": 3306},
    "tags": {"sql.query": "select version()"}
}, {
    "traceId": "8cafeeba762c479e",
    "parentId": "c149cb2af458c95d",
    "id": "b5809e988d9b47f8",
    "kind": "SERVER",
    "name": "post /user/getuserserver",
    "timestamp": 1623828578523548,
    "duration": 709280,
    "localEndpoint": {"serviceName": "scdemo-server"},
    "remoteEndpoint": {"ipv4": "10.49.196.1", "port": 65248},
    "tags": {
        "http.method": "POST",
        "http.path": "/user/getUserServer",
        "mvc.controller.class": "UserController",
        "mvc.controller.method": "getUser"
    },
    "shared": true
}]

traceId  一次請求全局只有一個traceId。用來在海量的請求中找到同一鏈路的幾次請求。比如servlet服務器接收到用戶請求,調用dubbo服務,然后將結果返回給用戶,整條鏈路只有一個traceId。開始於用戶請求,結束於用戶收到結果。
id  即spanId,一個鏈路中每次請求都會有一個spanId。例如一次rpc,一次sql都會有一個單獨的spanId從屬於traceId。
parentId 當前 Span 的父 Span id,通過 parentId 來確定 Span 之間的依賴關系,如果沒有 parentId,表示當前 Span 為根 Span。
timestamp Span 創建時的時間戳,單位是微秒
duration 本次請求的持續時間,單位是微秒
annotations 用於記錄請求的開始和結束:

cs Clent Sent 客戶端發起請求的時間。
cr Client Receive 客戶端收到處理完請求的時間。
ss Server Receive 服務端處理完邏輯的時間。
sr Server Receive 服務端收到調用端請求的時間。
sr - cs = 請求在網絡上的耗時
ss - sr = 服務端處理請求的耗時
cr - ss = 回應在網絡上的耗時
cr - cs = 一次調用的整體耗時

4、Zipkin 工作過程

       當發起一次調用時,Zipkin 的客戶端會在入口處為整條調用鏈路生成一個全局唯一的 trace id,並為這條鏈路中的每一次分布式調用生成一個 span id。span 與 span 之間可以有父子嵌套關系,代表分布式調用中的上下游關系。span 和 span 之間可以是兄弟關系,代表當前調用下的兩次子調用。一個 trace 由一組 span 組成,可以看成是由 trace 為根節點,span 為若干個子節點的一棵樹。
       Zipkin 會將 trace 相關的信息在調用鏈路上傳遞,並在每個調用邊界結束時異步的把當前調用的耗時信息上報給 Zipkin Server。Zipkin Server 在收到 trace 信息后,將其存儲起來。隨后 Zipkin 的 Web UI 會通過 API 訪問的方式從存儲中將 trace 信息提取出來分析並展示。

5、Zipkin 效果展示

Zipkin 可以查看一次請求的整個鏈路的調用情況:

也可以查看各模塊之間的依賴情況:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM