微服務(wù)監(jiān)控之分布式鏈路追蹤技術(shù) Sleuth + Zipkin

微服務(wù)監(jiān)控之分布式鏈路追蹤技術(shù) Sleuth + Zipkin

1.問題場景

為了?撐?益增?的龐?業(yè)務(wù)量,我們會使?微服務(wù)架構(gòu)設(shè)計我們的系統(tǒng),使得我們的系統(tǒng)不僅能

夠通過集群部署抵擋流量的沖擊,?能根據(jù)業(yè)務(wù)進?靈活的擴展。

那么,在微服務(wù)架構(gòu)下,?次請求少則經(jīng)過三四次服務(wù)調(diào)?完成,多則跨越??個甚?是上百個服

務(wù)節(jié)點。那么問題接踵?來:

1)如何動態(tài)展示服務(wù)的調(diào)?鏈路?(?如A服務(wù)調(diào)?了哪些其他的服務(wù)---依賴關(guān)系)

2)如何分析服務(wù)調(diào)?鏈路中的瓶頸節(jié)點并對其進?調(diào)優(yōu)?(?如A—>B—>C,C服務(wù)處理時間特別

?)

3)如何快速進?服務(wù)鏈路的故障發(fā)現(xiàn)?

分布式鏈路追蹤技術(shù)

如果我們在?個請求的調(diào)?處理過程中,在各個鏈路節(jié)點都能夠記錄下?志,并最終將?志進?集

中可視化展示,那么我們想監(jiān)控調(diào)?鏈路中的?些指標就有希望了~~~?如,請求到達哪個服務(wù)實

例?請求被處理的狀態(tài)怎樣?處理耗時怎樣?這些都能夠分析出來了...

分布式環(huán)境下基于這種想法實現(xiàn)的監(jiān)控技術(shù)就是就是分布式鏈路追蹤(全鏈路追蹤)。

市場上的分布式鏈路追蹤?案

分布式鏈路追蹤技術(shù)已然成熟,產(chǎn)品也不少,國內(nèi)外都有,?如

Spring Cloud Sleuth + Twitter Zipkin

阿?巴巴的“鷹眼”

?眾點評的“CAT”

美團的“Mtrace”

京東的“Hydra”

新浪的“Watchman”

另外還有最近也被提到很多的Apache Skywalking。

2.分布式鏈路追蹤技術(shù)核?思想

本質(zhì):記錄?志

為了追蹤整個調(diào)?鏈路,肯定需要記錄?志,?志記錄是基礎(chǔ),在此之上肯定有?些理論概念,當下主

流的的分布式鏈路追蹤技術(shù)/系統(tǒng)所基于的理念都來?于Google的?篇論?《Dapper, a Large-Scale

Distributed Systems Tracing Infrastructure》,核?理念如下:

Trace:服務(wù)追蹤的追蹤單元是從客戶發(fā)起請求(request)抵達被追蹤系統(tǒng)的邊界開始,到被追蹤系統(tǒng)

向客戶返回響應(yīng)(response)為?的過程

Trace ID:為了實現(xiàn)請求跟蹤,當請求發(fā)送到分布式系統(tǒng)的??端點時,只需要服務(wù)跟蹤框架為該請求

創(chuàng)建?個唯?的跟蹤標識Trace ID,同時在分布式系統(tǒng)內(nèi)部流轉(zhuǎn)的時候,框架失蹤保持該唯?標識,直

到返回給請求?

?個Trace由?個或者多個Span組成,每?個Span都有?個SpanId,Span中會記錄TraceId,同時還有

?個叫做ParentId,指向了另外?個Span的SpanId,表明??關(guān)系,其實本質(zhì)表達了依賴關(guān)系

Span ID:為了統(tǒng)計各處理單元的時間延遲,當請求到達各個服務(wù)組件時,也是通過?個唯?標識Span

ID來標記它的開始,具體過程以及結(jié)束。對每?個Span來說,它必須有開始和結(jié)束兩個節(jié)點,通過記錄

開始Span和結(jié)束Span的時間戳,就能統(tǒng)計出該Span的時間延遲,除了時間戳記錄之外,它還可以包含

?些其他元數(shù)據(jù),?如時間名稱、請求信息等。

每?個Span都會有?個唯?跟蹤標識 Span ID,若?個有序的 span 就組成了?個 trace。

Span可以認為是?個?志數(shù)據(jù)結(jié)構(gòu),在?些特殊的時機點會記錄了?些?志信息,?如有時間戳、

spanId、TraceId,parentIde等,Span中也抽象出了另外?個概念,叫做事件,核?事件如下

CS :client send/start 客戶端/消費者發(fā)出?個請求,描述的是?個span開始

SR: server received/start 服務(wù)端/?產(chǎn)者接收請求 SR-CS屬于請求發(fā)送的?絡(luò)延遲

SS: server send/fifinish 服務(wù)端/?產(chǎn)者發(fā)送應(yīng)答 SS-SR屬于服務(wù)端消耗時間

CR:client received/fifinished 客戶端/消費者接收應(yīng)答 CR-SS表示回復(fù)需要的時間(響應(yīng)的?絡(luò)延

遲)


Spring Cloud Sleuth (追蹤服務(wù)框架)可以追蹤服務(wù)之間的調(diào)?,Sleuth可以記錄?個服務(wù)請求經(jīng)過哪

些服務(wù)、服務(wù)處理時?等,根據(jù)這些,我們能夠理清各微服務(wù)間的調(diào)?關(guān)系及進?問題追蹤分析。

耗時分析:通過 Sleuth 了解采樣請求的耗時,分析服務(wù)性能問題(哪些服務(wù)調(diào)??較耗時)

鏈路優(yōu)化:發(fā)現(xiàn)頻繁調(diào)?的服務(wù),針對性優(yōu)化等

Sleuth就是通過記錄?志的?式來記錄蹤跡數(shù)據(jù)的

注意:我們往往把Spring Cloud SleuthZipkin ?起使?,把 Sleuth 的數(shù)據(jù)信息發(fā)送給 Zipkin

?聚合,利? Zipkin 存儲并展示數(shù)據(jù)。

3. Sleuth + Zipkin

1)每?個需要被追蹤蹤跡的微服務(wù)?程都引?依賴坐標

<!--鏈路追蹤-->
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

2)每?個微服務(wù)都修改application.yml配置?件,添加?志級別

#分布式鏈路追蹤
logging:
 level:
 org.springframework.web.servlet.DispatcherServlet: debug
 org.springframework.cloud.sleuth: debug

3)結(jié)合 Zipkin 展示追蹤數(shù)據(jù)

Zipkin 包括Zipkin Server和 Zipkin Client兩部分,Zipkin Server是?個單獨的服務(wù),Zipkin Client就是具體的微服務(wù)

  1. Zipkin Server 構(gòu)建

    <!--zipkin-server的依賴坐標-->
     <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-server</artifactId>
        <version>2.12.3</version>
     <exclusions>
     <!--排除掉log4j2的傳遞依賴,避免和springboot依賴的?志組件沖突-->
     <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
     </exclusion>
     </exclusions>
     </dependency>
     <!--zipkin-server ui界?依賴坐標-->
     <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-ui</artifactId>
        <version>2.12.3</version>
     </dependency>
    
  1. 添加注解啟動

    @EnableZipkinServer

  2. 添加配置

    management:
      metrics:
       web:
         server:
           auto-time-requests: false # 關(guān)閉?動檢測請求
    
  1. Zipkin Client 構(gòu)建

    <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-zipkin</artifactId>
    </dependency>
    
  1. 配置:添加對zipkin server的引?

    spring:
      zipkin:
        base-url: http://127.0.0.1:9411 # zipkin server的請求地址
        sender:
     # web 客戶端將蹤跡?志數(shù)據(jù)通過?絡(luò)請求的?式傳送到服務(wù)端,另外還有配置
     # kafka/rabbit 客戶端將蹤跡?志數(shù)據(jù)傳遞到mq進?中轉(zhuǎn)
        type: web
     sleuth:
       sampler:
     # 采樣率 1 代表100%全部采集 ,默認0.1 代表10% 的請求蹤跡數(shù)據(jù)會被采集
     # ?產(chǎn)環(huán)境下,請求量?常?,沒有必要所有請求的蹤跡數(shù)據(jù)都采集分析,對于?絡(luò)包括server端壓?都是?較?的,可以配置采樣率采集?定?例的請求的蹤跡數(shù)據(jù)進?分析即可
       probability: 1
    

3.1 Zipkin持久化到mysql

  1. 引入依賴

    <dependency>
     <groupId>io.zipkin.java</groupId>
     <artifactId>zipkin-autoconfigure-storage?mysql</artifactId>
     <version>2.12.3</version>
     </dependency>
     <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     </dependency>
     <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid-spring-boot-starter</artifactId>
     <version>1.1.10</version>
     </dependency>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-tx</artifactId>
     </dependency>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-jdbc</artifactId>
     </dependency>
    
  1. 配置yaml

    # 指定zipkin持久化介質(zhì)為mysql
    zipkin:
      storage:
        type: mysql
    
  1. 啟動類中注?事務(wù)管理器

    @Bean
    public PlatformTransactionManager txManager(DataSource dataSource) {
     return new DataSourceTransactionManager(dataSource);
    }
    
    1. 初始數(shù)據(jù)庫腳本
    CREATE TABLE IF NOT EXISTS zipkin_spans (
     `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this
    means the trace uses 128 bit traceIds instead of 64 bit',
     `trace_id` BIGINT NOT NULL,
     `id` BIGINT NOT NULL,
     `name` VARCHAR(255) NOT NULL,
     `remote_service_name` VARCHAR(255),
     `parent_id` BIGINT,
     `debug` BIT(1),
     `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for
    endTs query and to implement TTL',
     `duration` BIGINT COMMENT 'Span.duration(): micros used for
    minDuration and maxDuration query',
     PRIMARY KEY (`trace_id_high`, `trace_id`, `id`)
    ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE
    utf8_general_ci;
    ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`)
    COMMENT 'for getTracesByIds';
    ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and
    getSpanNames';
    ALTER TABLE zipkin_spans ADD INDEX(`remote_service_name`) COMMENT 'for
    getTraces and getRemoteServiceNames';
    ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces
    ordering and range';
    CREATE TABLE IF NOT EXISTS zipkin_annotations (
     `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this
    means the trace uses 128 bit traceIds instead of 64 bit',
     `trace_id` BIGINT NOT NULL COMMENT 'coincides with
    zipkin_spans.trace_id',
     `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',
     `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or
    Annotation.value if type == -1',
     `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be
    smaller than 64KB',
     `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if
    Annotation',
     `a_timestamp` BIGINT COMMENT 'Used to implement TTL;
    Annotation.timestamp or zipkin_spans.timestamp',
     `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is
    null',
     `endpoint_ipv6` BINARY(16) COMMENT 'Null when
    Binary/Annotation.endpoint is null, or no IPv6 address',
     `endpoint_port` SMALLINT COMMENT 'Null when
    Binary/Annotation.endpoint is null',
     `endpoint_service_name` VARCHAR(255) COMMENT 'Null when
    Binary/Annotation.endpoint is null'
    ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE
    utf8_general_ci;
    ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`,
    `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert
    on duplicate';
    ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`,
    `span_id`) COMMENT 'for joining with zipkin_spans';
    ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`)
    COMMENT 'for getTraces/ByIds';
    ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`)
    COMMENT 'for getTraces and getServiceNames';
    ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for
    getTraces and autocomplete values';
    ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for
    getTraces and autocomplete values';
    ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`,
    `a_key`) COMMENT 'for dependencies job';
    CREATE TABLE IF NOT EXISTS zipkin_dependencies (
     `day` DATE NOT NULL,
     `parent` VARCHAR(255) NOT NULL,
     `child` VARCHAR(255) NOT NULL,
     `call_count` BIGINT,
     `error_count` BIGINT,
     PRIMARY KEY (`day`, `parent`, `child`)
    ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE
    utf8_general_ci;
    
最后編輯于
?著作權(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ù)。

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