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

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

一、Zipkin 結構

1.一、Zipkin 服務端

 Zipkin 服務端由四部分組成:sql

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

1.二、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.三、Transport

鏈接 Zipkin 服務端和客戶端的數據傳輸通道(Transport) 能夠爲:Http, Kafka, Scribe。mvc

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

二、Zipkin 傳播規範

當上遊服務經過 HTTP 調用下游服務,如何將兩個服務中的全部 span 串聯起來,造成一個 trace,這就須要上游服務將 traceId 等信息傳遞給下游服務,而不能讓下游從新生成一個 traceId。Zipkin 經過 B3 傳播規範(B3 Propagation),將相關信息(如 traceId、spanId 等)經過 HTTP 請求 Header 傳遞給下游服務:框架

三、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 = 一次調用的總體耗時

四、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 信息提取出來分析並展現。elasticsearch

五、Zipkin 效果展現

Zipkin 能夠查看一次請求的整個鏈路的調用狀況:

也能夠查看各模塊之間的依賴狀況:

相關文章
相關標籤/搜索