分布式服务调用链路跟踪——Spring Cloud Sleuth + Zipkin

前言

微服务架构下,会有很多微服务,服务之间调用关系会非常复杂,就非常有必要对每个请求的完整调用链进行跟踪,了解调用了那些服务,当出现问题时可以快速定位。

Spring Cloud Sleuth 为 Spring Cloud 实现了一个分布式跟踪解决方案,该组件大量借签了 Dapper、Zipkin 和 HTrace。

对于大多数用户来说,Sleuth 应该是不可见的,它会自动检测系统的交互,可以在日志中捕获跟踪数据,或将其它送到远程日志收集服务器。

Spring Cloud Sleuth 官方文档Sleuth Zipkin 日志存储跟踪示例Zipkin GitHub Zipkin UI 示例OpenZipkin/Brave 捕获延迟信息的库

1. Sleuth

在详细介绍 Sleuth 之前,先通过 Spring Cloud 集成 Sleuth 来查看效果,可能更直观的理解。

  • 准备工作

这里我们需要创建两个微服务Server-Provider1和Server-Provider2,它们都具有一个名为hello的REST接口,Server-Provider1的hello接口依赖于Server-Provider2的hello接口。

并将这两个服务注册到Eureka-Server服务注册中心集群。Eureka-Server服务注册中心集群直接使用https://mrbird.cc/Spring-Cloud-Eureka.html里构建的即可,这里不再赘述。

  • 创建Server-Provider1

1、新建一个Spring Boot工程,artifactId为Server-Provider1,并引入如下依赖:

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

spring-cloud-starter-eureka用于注册微服务,spring-cloud-starter-ribbon用于调用Server-Provider2提供的服务,spring-cloud-starter-sleuth为Spring Cloud Sleuth依赖,用于跟踪微服务请求。

2、接着在配置文件application.yml里添加如下配置:

spring:
  application:
    name: server-provider1
server:
  port: 9000

eureka:
  client:
    serviceUrl:
      defaultZone: http://mrbird:123456@peer1:8080/eureka/,http://mrbird:123456@peer2:8081/eureka/

配置中指定了微服务名称为server-provider1,端口号为9000以及服务注册中心地址。

3、配置logback-spring.xml文件,在Pattern中使用 ${LOG_LEVEL_PATTERN:-%5p},日志中会输出TraceId的信息:

    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %black(%d{ISO8601}) %highlight(${LOG_LEVEL_PATTERN:-%5p}) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable
            </Pattern>
        </layout>
    </appender>

4、然后我们在入口类中添加@EnableDiscoveryClient注解,开启服务的注册与发现。并且注册RestTemplate,用于Ribbon服务远程调用:

@SpringBootApplication
@EnableDiscoveryClient
public class DemoApplication {

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

5、最后编写REST接口:

@RestController
@RequestMapping("hello")
public class HelloController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping
    public String hello() {
        logger.info("调用server-provider1的hello接口");
        return this.restTemplate.getForEntity("http://server-provider2/hello", String.class).getBody();
    }
}

在hello接口中,我们通过RestTemplate远程调用了server-provider2的hello接口。

  • 创建Server-Provider2

1、新建一个新建一个Spring Boot工程,artifactId为Server-Provider2,依赖和Server-Provider1相同,logback-spring.xml和Server-Provider1相同。

2、在application.yml中添加如下配置:

spring:
  application:
    name: server-provider2
server:
  port: 9001

eureka:
  client:
    serviceUrl:
      defaultZone: http://mrbird:123456@peer1:8080/eureka/,http://mrbird:123456@peer2:8081/eureka/

3、在入口类中添加@EnableDiscoveryClient注解,开启服务注册与发现,跟Server-Provider1相同。

4、最后编写一个REST接口,供Server-Provider1调用:

@RestController
@RequestMapping("hello")
public class HelloController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @GetMapping
    public String hello() {
        logger.info("调用server-provider2的hello接口");
        return "hello world";
    }
}

至此,Server-Provider2也搭建完了。

  • 测试Spring Cloud Sleuth

启动8080和8081Eureka-Server集群,然后分别启动Server-Provider1和Server-Provider2。访问http://localhost:8080/查看服务是否都启动成功:

可见服务都启动成功了,我们往Server-provider1发送http://localhost:9000/hello请求,

然后观察各自的日志:

Server-Provider1:

2018-06-25 10:13:40.921  INFO [server-provider1,939ca3c1d060ed40,939ca3c1d060ed40,false] 12516 --- [nio-9000-exec-6] c.e.demo.controller.HelloController      : 调用server-provider1的hello接口

Server-Provider2:

2018-06-25 10:13:40.931  INFO [server-provider2,939ca3c1d060ed40,3f31114e88154074,false] 6500 --- [nio-9001-exec-3] c.e.demo.controller.HelloController      : 调用server-provider2的hello接口

可以看到,日志里出现了[server-provider2,939ca3c1d060ed40,3f31114e88154074,false]信息,这些信息由Spring Cloud Sleuth生成,用于跟踪微服务请求链路。

这些信息包含了4个部分的值,它们的含义如下:

  1. server-provider2 微服务的名称,与spring.application.name对应;

  2. 939ca3c1d060ed40 称为Trace ID,在一条完整的请求链路中,这个值是固定的。观察上面的日志即可证实这一点;

  3. 3f31114e88154074 称为Span ID,它表示一个基本的工作单元;

  4. false 表示是否要将该信息输出到Zipkin等服务中来收集和展示,这里我们还没有集成Zipkin,所以为false。

通过 Spring Cloud 集成 Sleuth 的示例,对 Sleuth 有了个基本的了解。

  1. 将 Span ID 和 Trace ID 添加到 Slf4J MDC 中,这样可以在日志聚合器中根据 Span ID 和 Trace ID 提取日志。
  2. 提供对常见分布式跟踪数据模型的抽象:traces(跟踪),spans(形成DAG(有向无环图)),注释,key-value注释。 松散地基于HTrace,但兼容Zipkin(Dapper)。
  3. Sleuth 常见的入口和出口点来自 Spring 应用(Servlet 过滤器、Rest Template、Scheduled Actions、消息通道、Zuul Filter、Feign Client)。
  4. 如果 spring-cloud-sleuth-zipkin 可用,Sleuth 将通过 HTTP 生成并收集与 Zipkin 兼容的跟踪。默认情况下,将跟踪数据发送到 localhost(端口:9411)上的 Zipkin 收集服务应用,可使用 spring.zipkin.baseUrl 修改服务器地址。
  1. Span:基本的工作单元。一个 RPC 调用就是一个新的 Span。Spand 还有此其他数据,如描述、时间戳事件、key-value 注释(tags)、Spand ID、进程ID(通常为 IP 地址)。
  2. Trace:整个请求的唯一ID,标识完速请求链路,是一组树形结构的 Span。
  3. Annotation:用于及时记录存在的事件。
    • cs:客户端发送。客户端发起一个请求。此注释标识 HTTP 请求的开始,也是 Span 的起点,。
    • sr:服务器收到,服务端接收到请求并准备开始处理。sr 时戳 - cs 时戳 = 网络延迟
    • ss:服务端发送。在完成请求处理时(当准备发送响应到客户端时)注释。ss 时戳 - sr 时戳 = 服务端处理请求耗时
    • cr:客户端收到。Span 的结束。客户端成功收到服务端的响应,标识这个 HTTP 请求的结束。cf 时戳 - cs 时戳 = 客户端发送出请求到收到服务端响应的总耗时

下图展示了Span和Trace在系统中的联系:

标记的每种颜色表示一个span(有七个span — 从A到G),请考虑以下标记:

Trace Id = X
Span Id = D
Client Sent

此标记表示当前span的Trace Id设置为XSpan Id设置为D,此外,还发生了Client Sent事件。

下图显示了span的父—子关系:

2. Zipkin

2.1 Zipkin概述

Zipkin 是一个分布式跟踪系统,用于收集、管理和查找跟踪数据。 它可以把分布式链路调用的顺序串起来,并计算链路中每个 RPC 调用的耗时,可以很直观的看出在整个调用链路中延迟问题。

Zipkin Server 提供了 UI 操作,可以非常方便地查看和搜索跟踪数据,直观的查看到链调用依赖关系。

该项目包括一个无依赖库和一个 spring-boot 服务器。 存储支持包括内存,JDBC(mysql),Cassandra 和 Elasticsearch。

在没有使用外部存储时,则默认使用内存存储数据,内存数据是有限且不可持久化的,所以建议使用外部存储,因日志数据通常很大,为了搜索日志的效率,所以建议使用 Elasticsearch。

apache/incubator-zipkin > Github, Zipkin 支持 Elasticsearch 存储的插件:storage-elasticsearch-httpzipkin-serverZipkin 官网

2.2 Zipkin整体架构

Zipkin 整体架构如下图所示,分成三个部分:

  • 【红框】Zipkin Tracer :负责从应用中,收集分布式场景下的调用链路数据,发送给 Zipkin Server 服务。
  • 【蓝框】Transport :链路数据的传输方式,目前有 HTTP、MQ 等等多种方式。
  • 【绿框】Zipkin Server :负责接收 Tracer 发送的 Tracing 数据信息,将其聚合处理并进行存储,后提供查询功能。之后,用户可通过 Web UI 方便获得服务延迟、调用链路、系统依赖等等。

Zipkin 的基础架构由 4 个核心组件构成:

  • Collector:收集器组件,处理从外部系统发过来的跟踪信息,将这些信息转换为 Zipkin 内部处理的 Span 格式,以支持后续的存储、分析、展示等功能。
  • Stroage:存储组件,主要处理收集器收到的跟踪信息,默认存储在内存中,也可通过 ES 或 JDBC 来存储。
  • Restful API:API 组件,提供外部访问接口。
  • Web UI:UI组件,基于 API 组件实现的 Web 控制台,用户可以很方便直观地查询、搜索和分析跟踪信息。

2.3 Zipkin数据采集

项目应用作为 Zipkin 客户端,发跟踪数据(主要是日志数据)发送到 Zipkin Server,并在 Zipkin 查看。

  • HTTP 方式发送

SpringCloud Sleuth 默认采用 Http 方式将 span 信息传输给 Zipkin。

依赖,pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

配置,application.properties:

# Zipkin Server 地址
spring.zipkin.base-url=http://localhost:8020
# Zipkin 采样比例,默认是 0.1
spring.sleuth.sampler.probability=1
# 发送方式(默认值)
spring.zipkin.sender.type=web

Zipkin 发送数据与接口调用次数默认比例为 0.1,即可能调用了 10 次接口,但 Zipkin 中只有一条数据。

这样设置,是因为在高并发下,如果所有数据都采集,大量的请求调用会产生海量的日志数据,特别是对于 HTTP 方式去发送采集的数据,收集过多的跟踪信息会对整个分布式系统的性能造成一定的影响。

这个比例可通过 spring.sleuth.sampler.probability 修改,为 1 的话表示全部发送。

虽然已有采样比例来收集数据,但 HTTP 发送方式仍对性能有影响,特别是在高并发性况下,如果 Zipkin 服务器重启或挂掉,这期间的采集数据就会丢失。

可以采用消息中间件的方式,异步通信,提高发送性能,数据也不会丢失。支持的MQ有RabbitMQ和Kafka。以下是使用Kafka的示例:

依赖,pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

配置,application.properties:

spring.zipkin.base-url=http://172.16.10.62:9411/
spring.sleuth.sampler.probability=1
spring.zipkin.sender.type=kafka
spring.zipkin.kafka.topic=zipkin
spring.kafka.bootstrap-servers=172.16.10.91:9092,172.16.10.92:9092,172.16.10.93:9092

2.4 Zipkin-Server 搭建

在官网 https://zipkin.io/pages/quickstart.html 提供了三种安装方式,我们这里采用官方已经构建好的 jar 包。

  • 下载 jar 包
# 创建目录
$ mkdir -p /opt/zipkin
$ cd /opt/zipkin

# 下载
$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
  • 编写启动脚本
vim /opt/zipkin/start-zipkin.sh

#!/bin/bash

nohup java
-DKAFKA_BOOTSTRAP_SERVERS=172.16.10.91:9092,172.16.10.92:9092,172.16.10.93:9092
-DSTORAGE_TYPE=elasticsearch
-DES_HOSTS=http://172.16.10.75:9200
-jar /opt/zipkin/zipkin.jar >> /opt/zipkin/zipkin.log 2>&1 &

参数介绍:

    • KAFKA_BOOTSTRAP_SERVERS:kafka broker地址
    • STORAGE_TYPE:数据存储类型,这里我们选择elasticsearch
    • ES_HOSTS :elasticsearch的地址
  • 赋予脚本可执行权限
chmod +x /opt/zipkin/start-zipkin.sh
  • 执行脚本启动服务
/opt/zipkin/start-zipkin.sh

查看 /opt/zipkin/zipkin.log 日志文件,如果文末出现如下日志,说明启动成功:

  •  简单使用

使用浏览器,访问 http://127.0.0.1:9411/ 地址,查看 Zipkin UI 界面。如下图所示:

2.5 Zipkin-Dependencies 搭建

在使用 Elasticsearch、Cassandra、MySQL 作为存储器后,需要使用 zipkin-dependencies,计算服务之间的依赖关系。不然,我们在 Zipkin UI 的「依赖」菜单,是看不到服务之间的依赖关系图。

  • 下载 jar 包
# 创建目录
$ mkdir -p /opt/zipkin
$ cd /opt/zipkin

# 下载
$ curl -sSL https://zipkin.io/quickstart.sh | bash -s io.zipkin.dependencies:zipkin-dependencies:LATEST zipkin-dependencies.jar

可能下载会比较慢,请耐心等待.

  • 编写启动脚本
vim /opt/zipkin/start-zipkin-dependencies.sh

#!/bin/bash

source /etc/profile
STORAGE_TYPE=elasticsearch ES_HOSTS=http://172.16.10.75:9200 nohup java -jar /opt/zipkin/zipkin-dependencies.jar >> /opt/zipkin/zipkin-dependencies.log 2>&1 &

参数介绍:

    • STORAGE_TYPE:存储类型
    • ES_HOSTS:若参数类型选择了es,则配置es的集群地址
  • 赋予脚本可执行权限
chmod +x /opt/zipkin/start-zipkin-dependencies.sh
  • 执行脚本启动服务

/opt/zipkin/start-zipkin-dependencies.sh

每执行一次,则会对历史数据计算一次结果服务之间的依赖关系的计算。查看 /opt/zipkin/zipkin-dependencies.log 输出结尾日志如下,代表执行成功:

因为 zipkin-dependencies.jar 实际是个 Spark Job,所以每次任务执行完后,JVM 进程就结束了。

我们需要参考 Running in a Spark cluster 文档,将 zipkin-dependencies.jar 部署到 Spark 集群中执行。

  • crontab定时调用脚本

不过考虑到可能我们没有 Spark 服务,所以我们也可以考虑使用 Linux 自带的 crontab 定时任务,配置如下,每分钟执行一次:

crontab -e
* * * * * /opt/zipkin/start-zipkin-dependencies.sh

3. 集成Zipkin(Dubbo 应用)示例

因为springcloud的微服务框架是基于http构建的,所以sleuth默认是只支持http。在2.0版本中提供了对dubbo的支持,其实看一下源码就知道,就只是一个DubboFilter。

zipkin本身支持多种collector和storage,默认采用异步http的collector,存储默认在内存中。考虑到对应用本身的性能影响,我们采用kafka来做collector,最大程度的解耦以及减少性能影响。

存储选用es,用mysql的话当数据量较大时会影响zipkin-server的查询速度。

搭建一个 Spring Cloud Sleuth 对 Dubbo 的远程 RPC 调用的链路追踪。总共有3个应用:

  1. 服务 API 项目
  2. 服务 Provider 项目
  3. 服务 Consumer 项目

该链路通过如下插件实现收集:

  brave-instrumentation-dubbo

友情提示:Brave 一共提供了两个插件,其中本文使用的 brave-instrumentation-dubbo 适用于 Dubbo 2.7.X 版本,而另外的 brave-instrumentation-dubbo-rpc 适用于 Dubbo 2.6.X 版本。

3.1 搭建 API 项目

创建项目,服务接口,定义 Dubbo Service API 接口,提供给消费者使用。

  • UserService

创建 UserService 接口,定义用户服务 RPC Service 接口。代码如下:

public interface UserService {

    /**
     * 根据指定用户编号,获得用户信息
     *
     * @param id 用户编号
     * @return 用户信息
     */
    String get(Integer id);

}

3.2 搭建服务提供者项目

创建项目,服务提供者,实现 API 项目定义的 Dubbo Service API 接口,提供相应的服务。

  • 引入依赖

创建 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">
    <parent>
        <artifactId>labx-13-sc-sleuth-dubbo</artifactId>
        <groupId>cn.iocoder.springboot.labs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>labx-13-sc-sleuth-dubbo-consumer</artifactId>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <spring.boot.version>2.2.4.RELEASE</spring.boot.version>
        <spring.cloud.version>Hoxton.SR1</spring.cloud.version>
        <spring.cloud.alibaba.version>2.2.0.RELEASE</spring.cloud.alibaba.version>
    </properties>

    <!--
        引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。
        在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系
    -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- 引入定义的 Dubbo API 接口 -->
        <dependency>
            <groupId>cn.iocoder.springboot.labs</groupId>
            <artifactId>labx-13-sc-sleuth-dubbo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 引入 Spring Cloud Alibaba Nacos Discovery 相关依赖,将 Nacos 作为注册中心,并实现对其的自动配置 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- 引入 Spring Cloud Alibaba Dubbo 相关依赖,实现呢 Dubbo 进行远程调用,并实现对其的自动配置 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>

        <!-- 引入 Spring Cloud Sleuth + Zipkin 相关依赖,实现对它们的自动配置,从而实现链路追踪 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

        <!-- Brave 针对 Dubbo 的插件,实现链路追踪 -->
        <dependency>
            <groupId>io.zipkin.brave</groupId>
            <artifactId>brave-instrumentation-dubbo</artifactId>
            <version>5.10.1</version>
        </dependency>
    </dependencies>

</project>

重点是引入 brave-instrumentation-dubbo 依赖,实现对 Dubbo 的链路追踪。

  • 配置文件

创建 application.yml 配置文件,添加相应配置项如下:

spring:
  application:
    name: demo-provider
  cloud:
    # Nacos 作为注册中心的配置项
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos 服务器地址

  # Zipkin 配置项,对应 ZipkinProperties 类
  zipkin:
    base-url: http://127.0.0.1:9411 # Zipkin 服务的地址

# Dubbo 配置项,对应 DubboConfigurationProperties 类
dubbo:
  scan:
    base-packages: cn.iocoder.springcloud.labx13.providerdemo.service # 指定 Dubbo 服务实现类的扫描基准包
  # Dubbo 服务暴露的协议配置,对应 ProtocolConfig Map
  protocols:
    dubbo:
      name: dubbo # 协议名称
      port: -1 # 协议端口,-1 表示自增端口,从 20880 开始
  # Dubbo 服务注册中心配置,对应 RegistryConfig 类
  registry:
    address: spring-cloud://127.0.0.1:8848 # 指定 Dubbo 服务注册中心的地址
  # Dubbo 服务提供者的配置,对应 ProviderConfig 类
  provider:
    filter: tracing
  # Spring Cloud Alibaba Dubbo 专属配置项,对应 DubboCloudProperties 类
  cloud:
    subscribed-services: '' # 设置订阅的应用列表,默认为 * 订阅所有应用

重点是设置 dubbo.provider.filter 配置项为 tracing,使用 brave-instrumentation-dubbo 提供的 TracingFilter 过滤器,实现对 Dubbo 的链路追踪

  • UserServiceImpl

创建 UserServiceImpl 类,实现 UserService 接口,用户服务具体实现类。代码如下:

@org.apache.dubbo.config.annotation.Service(protocol = "dubbo", version = "1.0.0")
public class UserServiceImpl implements UserService {

    @Override
    public String get(Integer id) {
        return "user:" + id;
    }
    
}
  • ProviderApplication

创建 ProviderApplication 类,服务提供者的启动类。代码如下:

@SpringBootApplication
public class ProviderApplication {

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

}

3.3 搭建服务消费者项目

创建项目,服务消费者,会调用 服务提供者 项目提供的 User Service 服务。

  • 引入依赖

创建 pom.xml 文件中,引入依赖。和「服务提供者项目 引入依赖」基本是一致的。

  • 配置文件

创建 application.yml 配置文件,添加相应配置项如下:

spring:
  application:
    name: demo-consumer
  cloud:
    # Nacos 作为注册中心的配置项
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

  # Zipkin 配置项,对应 ZipkinProperties 类
  zipkin:
    base-url: http://127.0.0.1:9411 # Zipkin 服务的地址

# Dubbo 配置项,对应 DubboConfigurationProperties 类
dubbo:
  # Dubbo 服务注册中心配置,对应 RegistryConfig 类
  registry:
    address: spring-cloud://127.0.0.1:8848 # 指定 Dubbo 服务注册中心的地址
  # Dubbo 服务提供者的配置,对应 ConsumerConfig 类
  consumer:
    filter: tracing
  # Spring Cloud Alibaba Dubbo 专属配置项,对应 DubboCloudProperties 类
  cloud:
    subscribed-services: demo-provider # 设置订阅的应用列表,默认为 * 订阅所有应用。

重点是设置 dubbo.consumer.filter 配置项为 tracing,使用 brave-instrumentation-dubbo 提供的 TracingFilter 过滤器,实现对 Dubbo 的链路追踪。

  • UserController

创建 UserController 类,提供调用 UserService 服务的 HTTP 接口。代码如下:

@RestController
@RequestMapping("/user")
public class UserController {

    @Reference(protocol = "dubbo", version = "1.0.0")
    private UserService userService;

    @GetMapping("/get")
    public String  get(@RequestParam("id") Integer id) {
        return userService.get(id);
    }

}
  • ConsumerApplication

创建 ConsumerApplication 类,服务消费者的启动类。代码如下:

@SpringBootApplication
public class ConsumerApplication {

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

}

3.4 简单测试

使用 ProviderApplication 启动服务提供者,使用 ConsumerApplication 启动服务消费者。

① 首先,使用 curl http://127.0.0.1:8080/user/get?id=1 命令,使用 Dubbo 调用 user-service 服务。因为,我们要追踪下该链路。

② 然后,继续使用浏览器,打开 http://127.0.0.1:9411/ 地址,查看链路数据。点击「查找」按钮,便可看到刚才我们调用接口的链路数据。如下图所示:

 一条链路经过 demo-consumer 和 demo-provider 两个服务,一共有三个 Span

③ 之后,我们点击该链路数据,可以看到一个 Trace 明细。如下图所示:

引用:

原文地址:https://www.cnblogs.com/caoweixiong/p/14469482.html