Spring Cloud實戰系列(七) - 服務鏈路追蹤Spring Cloud Sleuth

相關

  1. Spring Cloud實戰系列(一) - 服務註冊與發現Eureka php

  2. Spring Cloud實戰系列(二) - 客戶端調用Rest + Ribbon java

  3. Spring Cloud實戰系列(三) - 聲明式客戶端Feign mysql

  4. Spring Cloud實戰系列(四) - 熔斷器Hystrix git

  5. Spring Cloud實戰系列(五) - 服務網關Zuul github

  6. Spring Cloud實戰系列(六) - 分佈式配置中心Spring Cloud Configweb

  7. Spring Cloud實戰系列(七) - 服務鏈路追蹤Spring Cloud Sleuthspring

  8. Spring Cloud實戰系列(八) - 微服務監控Spring Boot Adminsql

  9. Spring Cloud實戰系列(九) - 服務認證受權Spring Cloud OAuth 2.0 數據庫

  10. Spring Cloud實戰系列(十) - 單點登陸JWT與Spring Security OAuth apache

前言

Spring Cloud Sleuth 的主要功能就是爲 分佈式系統 提供 追蹤解決方案,而且兼容支持了 Zipkin,只須要在 pom.xml 文件中引入相應的 依賴 便可。本文主要講述 服務追蹤組件 ZipkinSpring Cloud Sleuth 集成了 Zipkin 組件。它主要用於 彙集 來自各個 異構系統實時監控數據,用來追蹤 微服務架構 下的 系統延時問題

正文

1. 相關術語

1.1. Span

Span 是一個基本的 工做單元,用於描述一次 RPC 調用,Span 經過一個 64 位的 spanId 做爲 惟一標識Zipkin 中的 Span 還有其餘數據信息,好比 摘要時間戳事件關鍵值註釋 (tags) 以及 進度 ID (一般是 IP 地址)。Span 在不斷的啓動和中止,同時記錄了 時間信息,一個 Span 建立後,必須在將來的某個時刻中止它。

1.2. Trace

一系列 Span 組成的一個 樹狀結構。例如,若是你正在跑一個大型 分佈式系統,可能須要建立一個 Trace

1.3. Annotation

表示 基本標註列表,一個 Annotation 能夠理解成 Span 生命週期中 重要時刻數據快照,好比一個 Annotation 中通常包含 發生時刻timestamp)、事件類型value)、端點endpoint)等信息。其中 Annotation事件類型 包含如下四類:

  • cs - Client Sent

客戶端 發起一個請求,這個 Annotion 描述了這個 Span 的開始。

  • sr - Server Received

服務端 得到請求並 準備開始 處理它,若是將 sr 減去 cs時間戳 即可獲得 網絡延遲

  • ss - Server Sent

服務端 完成請求處理,若是將 ss 減去 sr時間戳,即可獲得 服務端 處理請求消耗的時間。

  • cr - Client Received

客戶端 成功接收到 服務端 的響應,若是將 cr 減去 cs時間戳,即可獲得 整個請求 所消耗的 總時間

2. 項目結構

本文案例主要由 四個模塊 組成:

  • eureka-server:做爲 服務註冊中心

  • zipkin-server:做爲 鏈路追蹤服務中心,負責存儲 鏈路數據

  • service-hi:對外暴露一個 測試接口,同時做爲 鏈路追蹤服務端,負責 產生鏈路數據

  • service-zuul:做爲 路由網關,負責 請求轉發,同時做爲 鏈路追蹤客戶端,產生 鏈路數據,並上傳至 zipkin-server

8761 端口 開啓 eureka-server 服務註冊中心,參考前面的文章便可,這裏再也不演示建立。

3. 構建zipkin-server

新建一個 Spring Boot 應用模塊 zipkin-server,它的 pom.xml 完整依賴以下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>io.github.ostenant.springcloud</groupId>
    <artifactId>zipkin-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>zipkin-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-server</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
複製代碼

在應用的入口類上, 加上註解 @EnableZipkinServer,開啓 Zipkin Server 的功能。

@EnableZipkinServer
@EnableEurekaClient
@SpringBootApplication
public class ZipkinServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZipkinServerApplication.class, args);
    }
}
複製代碼

配置文件 application.yml 中指定服務端口號爲 9411,並向 Eureka 註冊中心進行 服務註冊

eureka:
 client:
 service-url:
 defaultZone: http://localhost:8761/eureka/
server:
 port: 9411
spring:
 application:
 name: zipkin-server
複製代碼

4. 構建service-hi

新建一個 Spring Boot 應用模塊 service-hi,在它的 pom.xml 中引入 引入起步依賴 spring-cloud-starter-zipkin,完整依賴以下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>io.github.ostenant.springcloud</groupId>
    <artifactId>service-hi</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-client</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
複製代碼

在它的 配置文件 application.yml 中經過配置項 spring.zipkin.base-url 指定 zipkin server 的地址。

eureka:
 client:
 serviceUrl:
 defaultZone: http://localhost:8761/eureka/
server:
 port: 8763
spring:
 application:
 name: service-hi
 zipkin:
  # base-url: http://localhost:9411/
  # 若在同一個註冊中心的話能夠啓用自動發現,省略base-url
 locator:
 discovery:
 enabled: true #自動發現
 sleuth:
 sampler:
 percentage: 1.0
複製代碼

到此爲止 ZipKin 客戶端 已經整合完畢,最後在 應用啓動類 上對外暴露一個 API 接口 方便測試

@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHiApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceHiApplication.class, args);
    }

    @Value("${server.port}")
    private String port;

    @RequestMapping("/hi")
    public String home(@RequestParam String name) {
        return "Hi " + name + ", I am from port: " + port;
    }
}
複製代碼

5. 構建service-zuul

新建一個 Spring Boot 應用模塊 service-zuul,在 pom.xml 中引入依賴 spring-cloud-starter-zipkin,完整依賴以下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>io.github.ostenant.springcloud</groupId>
    <artifactId>service-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>service-zuul</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
複製代碼

在它的 配置文件 application.yml 中經過配置項 spring.zipkin.base-url 指定 zipkin server 的地址。同時指定 service-hi 基於 zuul服務路徑 匹配前綴。

server:
 port: 8769
spring:
 application:
 name: service-zuul
 client:
 service-url:
 defaultZone: http://localhost:8761/eureka/
 sleuth:
 sampler:
 percentage: 1.0
 zipkin:
    # base-url: http://localhost:9411/
    # 若在同一個註冊中心的話能夠啓用自動發現,省略base-url
 locator:
 discovery:
 enabled: true #自動發現
zuul:
 routes:
 api-hi:
 path: /api-hi/**
 serviceId: service-hi
複製代碼

到這裏能夠發現,引入 ZipKin 服務只須要 導依賴配置屬性 兩步便可。在應用的 啓動類 上使用 @EnableZuulProxy 註解開啓 路由網關

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ServiceZuulApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceZuulApplication.class, args);
    }
}
複製代碼

6. 測試追蹤過程

完整 鏈路追蹤模塊 搭建完畢,總結一下:

  1. 搭建一臺 zipkin server 做爲 鏈路服務中心

  2. 給各個 服務 引入 zipkin 依賴,配置 zipkin server 地址便可。

下面按順序依次啓動 eureka-serverservice-zipkinservice-hiservice-zuul。訪問服務網關,地址爲: http://localhost:8769/api-hi/hi?name=vainlgory,服務響應內容以下:

Hi Vainlgory, I am from port: 8763

而後訪問 http://localhost:9411,即訪問 ZipKin 提供的可視化頁面。

這個界面用於顯示 ZipKin Server 收集的 鏈路數據,能夠根據 服務名開始時間結束時間請求消耗的時間 等條件來查找。單擊 Find Tracks按鈕,能夠查看請求的 調用時間消耗時間,以及請求的 鏈路狀況

單擊頂部的 Dependencies 按鈕,能夠查看服務的 依賴關係

7. 在鏈路數據中添加自定義數據

如今須要實現一個功能:在 鏈路數據 中加上請求的 操做人。本案例在 service-zuul 網關服務 中實現。

  1. 新建一個 ZuulFilter 過濾器,它的類型爲 post 類型,order900,開啓 攔截功能

  2. 在過濾器的 攔截邏輯方法 run() 裏面,經過 TraceraddTag() 方法加上 自定義 的數據,在本案例中加上了鏈路的 操做人

  3. 也能夠在這個 過濾器 中獲取 當前鏈路traceld 信息,traceld 做爲 鏈路數據惟一標識,能夠存儲在 log 日誌中,方便後續查找,本案例只是將 traceld 的信息簡單地打印在控制檯上。代碼以下:

@Component
public class LoggerFileter extends ZuulFilter {
    @Autowired
    private Tracer tracer;

    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return 900;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        tracer.addTag("operator","forezp");
        System.out.println(tracer.getCurrentSpan().traceIdString());
        return null;
    }
}
複製代碼

8. 使用RabbitMQ傳輸鏈路數據

首先改造 zipkin-server 項目模塊,在它的 pom.xml 文件中將 zipkin-server 的依賴去掉,加上 spring-cloud-sleuth-zipkin-streamspring-cloud-starter-stream-rabbit 的依賴,配置以下:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
複製代碼

zipkin-server 的配置文件 application.yml 中加上 RabbitMQ 的配置,包括 主機名端口用戶名密碼,代碼以下:

spring:
 rabbitmq:
 host: localhost
 port: 5672
 username: guest
 password: guest
複製代碼

在應用的啓動類 ZipkinServerApplication 上把註解 @EnableZipkinServer 替換爲註解 @EnableZipkinStreamServer,開啓 ZipkinStreamServer,代碼以下:

@EnableEurekaClient
@SpringBootApplication
@EnableZipkinStreamServer
public class ZipkinServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZipkinServerApplication.class, args);
    }
}
複製代碼

如今來改造 Zipkin Client(包括 service-zuulservice-hi 兩個模塊),分別在它們的 pom.xml 文件中將 spring-cloud-starter-zipkin 依賴改成 spring-cloud-sleuth-zipkin-streamspring-cloud-starter-stream-rabbit,代碼以下:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
複製代碼

和前面的 zipkin-server 模塊同樣,同時在配置文件 applicayion.yml 加上 RabbitMQ 的配置。這樣,就將鏈路的 數據上傳HTTP 改成用 消息代組件 RabbitMQ 的方式。

9. 在MySQL數據庫中存儲鏈路數據

在上面的例子中,Zipkin Server 將數據存儲在 內存 中,一旦應用服務 重啓,以前的 鏈路數據所有丟失,這時候就須要引入 持久化機制Zipkin 支持將 鏈路數據 存儲在 MySQLElasticsearchCassandra 數據庫中。本節講解如何使用 MySQL 存儲。

Zipkin Client 有兩種方式將 鏈路數據 傳輸到 Zipkin Server 中,一種是使用 HTTP,另外一種是使用 RabbitMQZipkin Server 經過這兩種方式來 收集鏈路數據,並存儲在 MySQL 中。

9.1. 使用HTTP傳輸鏈路數據

zipkin-server 模塊的 pom.xml 文件加上如下依賴:

  • Zipkin Server 的依賴 zipkin-server

  • ZipkinMySQL 存儲依賴 zipkin-storage-mysql

  • Zipkin ServerUI 界面依賴 zipkin-autoconfigure-ui

  • MySQL 的鏈接器依賴 mysql-connector-java

  • JDBC起步依賴 spring-boot-starter-jdbc

代碼以下:

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-server</artifactId>
    <version>1.19.0</version>
</dependency>
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-storage-mysql</artifactId>
    <version>1.19.0</version>
</dependency>
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
複製代碼

zipkin-server 模塊的 配置文件 application.yml 中加上 數據源 的配置,包括 數據庫Url用戶名密碼鏈接驅動,而且須要配置 zipkin.storage.typemysql,代碼以下:

spring:
 datasource:
 driver-class-name: com.mysql.jdbc.Driver
 url: jdbc:mysql://localhost:3306/spring-cloud-zipkin?useUnicode=true&characterEncoding=utf8&useSSL=false
 username: root
 password: 123456
zipkin:
 storage:
 type: mysql
複製代碼

另外須要在 MySQL 數據庫中放置數據庫的 初始化腳本,建立包括 zipkin_spanszipkin_annotationszipkin_dependencies 這幾張表。

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,
  `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'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate';
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations';
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(`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';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces';
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
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);
複製代碼

最後須要在應用的啓動類 ZipkinServerApplication 中注入 MySQLStorageBean,代碼以下:

@Bean
public MySQLStorage mySQLStorage(DataSource datasource) {
    return MySQLStorage.builder()
        .datasource(datasource)
        .executor(Runnable::run)
        .build();
}
複製代碼

只須要上述步驟,便可將使用 HTTP 傳輸的 鏈路數據 存儲在 MySQL 數據庫中。

9.2. 使用RabbitMQ傳輸鏈路數據

本節的案例是在使用 RabbitMQ 傳輸數據 基礎上進行改造的,只須要改造 zipkin-server 的工程。

zipkin-server 工程的 pom.xml 文件中加上 MySQL鏈接器依賴 mysql-connector-javaJDBC起步依賴 spring-boot-starter-jdbc,代碼以下:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
複製代碼

zipkin-server 模塊的 配置文件 application.yml 中加上 數據源 的配置,包括數據庫的 Uri用戶名密碼鏈接驅動,一樣的配置 zipkin.storage.typemysql,代碼以下:

spring:
 datasource:
 url: jdbc:mysql://localhost:3306/spring-cloud-zipkin?useUnicode=true&characterEncoding=utf8&useSSL=false
 username: root
 password: 123456
 driver-class-name: com.mysql.jdbc.Driver
zipkin:
 storage:
 type: mysql
複製代碼

另外須要在 MySQL數據庫中初始化 數據庫腳本,具體同上一節。

10. 在ElasticSearch中存儲鏈路數據

併發高 的狀況下,使用 MySQL 存儲 鏈路數據 顯然不合理,這時能夠選擇使用 ElasticSearch 做爲存儲。

下載並安裝 ElasticSearchKibana,下載地址爲 www.elastic.co/products/el…。安裝完成後啓動,其中 ElasticSearch默認端口號9200Kibana默認端口號5601

本節是在 第八節 的基礎上進行改造。首先在 pom.xml 文件中加上 zipkin 的依賴和 zipkin-autoconfigure-storage-elasticsearch-http 的依賴,代碼以下:

<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin</artifactId>
    <version>1.28.1</version>
</dependency>
<dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
    <version>1.28.1</version>
</dependency>
複製代碼

在應用的配置文件 application.yml 中加上 Zipkin 的配置,配置了 zipkin存儲類型type) 爲 Elasticsearch,使用的 存儲組件StorageComponent)爲 Elasticsearch,而後須要配置 Elasticsearch,包括 hosts( 能夠配置 多個實例,用 「,」 隔開)。具體配置代碼以下:

zipkin:
 storage:
 type: elasticsearch
 StorageComponent: elasticsearch
 elasticsearch:
 cluster: elasticsearch
 max-requests: 30
 index: zipkin
 index-shards: 3
 index-replicas: 1
 hosts: localhost:9200
複製代碼

只須要完成這些配置,Zipkin Server鏈路數據 就能夠存儲在 ElasticSearch 裏面。

11. 用Kibana展現鏈路數據

上一節講述瞭如何將 鏈路數據 存儲在 ElasticSearch 中,ElasticSearch 能夠和 Kibana 結合,將 鏈路數據 展現在 Kibana 上。安裝完成後啓動 KibanaKibana 默認會向 本地端口9200ElasticSearch 讀取數據。Kibana默認端口5601,訪問 Kibana 的主頁 http://localhost:5601

單擊 Management 按鈕,而後單擊 Add New,添加一個 index。上一節 ElasticSearch 中寫入 鏈路數據index 配置的是 zipkin,在 Kibana 界面上填寫 zipkin-*,單擊 Create 按鈕,建立完成 index 後,單擊 Discover,頁面上出現 鏈路數據

參考

  • 方誌朋《深刻理解Spring Cloud與微服務構建》

歡迎關注技術公衆號: 零壹技術棧

零壹技術棧

本賬號將持續分享後端技術乾貨,包括虛擬機基礎,多線程編程,高性能框架,異步、緩存和消息中間件,分佈式和微服務,架構學習和進階等學習資料和文章。

相關文章
相關標籤/搜索