转载

Spring Cloud实战系列(七) - 服务链路追踪Spring Cloud Sleuth

Spring Cloud Sleuth 的主要功能就是为 分布式系统 提供 追踪解决方案 ,并且兼容支持了 Zipkin ,只需要在 pom.xml 文件中引入相应的 依赖 即可。本文主要讲述 服务追踪组件 Zipkin , Spring 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-server 、 service-zipkin 、 service-hi 和 service-zuul 。访问服务网关,地址为: http://localhost:8769/api-hi/hi?name=vainlgory,服务响应内容如下:

Hi Vainlgory, I am from port: 8763

然后访问 http://localhost:9411 ,即访问 ZipKin 提供的可视化页面。

Spring Cloud实战系列(七) - 服务链路追踪Spring Cloud Sleuth

这个界面用于显示 ZipKin Server 收集的 链路数据 ,可以根据 服务名 、 开始时间 、 结束时间 、 请求消耗的时间 等条件来查找。单击 Find Tracks 按钮,可以查看请求的 调用时间 、 消耗时间 ,以及请求的 链路情况 。

单击顶部的 Dependencies 按钮,可以查看服务的 依赖关系 。

Spring Cloud实战系列(七) - 服务链路追踪Spring Cloud Sleuth

7. 在链路数据中添加自定义数据

现在需要实现一个功能:在 链路数据 中加上请求的 操作人 。本案例在 service-zuul 网关服务 中实现。

  1. 新建一个 ZuulFilter 过滤器 ,它的类型为 post 类型, order 为 900 ,开启 拦截功能 。

  2. 在过滤器的 拦截逻辑方法 run() 里面,通过 Tracer 的 addTag() 方法加上 自定义 的数据,在本案例中加上了链路的 操作人 。

  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-stream 和 spring-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-zuul 和 service-hi 两个模块),分别在它们的 pom.xml 文件中将 spring-cloud-starter-zipkin 依赖改为 spring-cloud-sleuth-zipkin-stream 和 spring-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 支持将 链路数据 存储在 MySQL 、 Elasticsearch 和 Cassandra 数据库中。本节讲解如何使用 MySQL 存储。

Zipkin Client 有两种方式将 链路数据 传输到 Zipkin Server 中,一种是使用 HTTP ,另一种是使用 RabbitMQ 。 Zipkin Server 通过这两种方式来 收集链路数据 ,并存储在 MySQL 中。

9.1. 使用HTTP传输链路数据

在 zipkin-server 模块的 pom.xml 文件加上以下依赖:

  • Zipkin Server 的依赖 zipkin-server

  • Zipkin 的 MySQL 存储依赖 zipkin-storage-mysql

  • Zipkin Server 的 UI 界面依赖 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.type 为 mysql ,代码如下:

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_spans 、 zipkin_annotations 和 zipkin_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 中注入 MySQLStorage 的 Bean ,代码如下:

@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-java 和 JDBC 的 起步依赖 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.type 为 mysql ,代码如下:

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 作为存储。

下载并安装 ElasticSearch 和 Kibana ,下载地址为 www.elastic.co/products/el… 。安装完成后启动,其中 ElasticSearch 的 默认端口号 为 9200 , Kibana 的 默认端口号 为 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 上。安装完成后启动 Kibana , Kibana 默认会向 本地端口 为 9200 的 ElasticSearch 读取数据。 Kibana 的 默认端口 为 5601 ,访问 Kibana 的主页 http://localhost:5601 。

单击 Management 按钮,然后单击 Add New ,添加一个 index 。上一节 ElasticSearch 中写入 链路数据 的 index 配置的是 zipkin ,在 Kibana 界面上填写 zipkin-* ,单击 Create 按钮,创建完成 index 后,单击 Discover ,页面上出现 链路数据 。

原文  https://juejin.im/post/5c56ead5e51d450165279d60
正文到此结束
Loading...