【微服务-链路跟踪】Spring Cloud Sleuth核心技术(上)

在前面几篇文章中,我们主要介绍了基于 Sentinel 如何对微服务架构提供限流、熔断保护。从本篇开始,我们继续完善微服务架构,通过介绍链路跟踪原理和基于SpringCloud Sleuth实现链路跟踪。

一、微服务链路跟踪原理

我们先看一个图,大家都知道在微服务架构下,系统的功能是由大量的微服务协调组成的,例如:电商创建订单业务就需要订单服务、库存服务、支付服务、短信通知服务逐级调用才能完成。而每个服务可能是由不同的团队进行开发,部署在成百上千台服务器上。

如此复杂的消息传递过程,当系统发生故障的时候,就需要一种机制对故障点进行快速定位,确认是哪个服务出了问题,链路追踪技术由此而生。

**所谓的链路追踪,就是运行时通过某种方式记录下服务之间的调用过程,在通过可视化的 UI 界面帮研发运维人员快速定位到出错点。**引入链路追踪,是微服务架构运维的底层基础,没有它,运维人员就像盲人摸象一样,根本无法了解服务间通信过程。

Spring Cloud 标准生态下内置了 Sleuth 这个组件,它通过扩展 Logging 日志的方式实现微服务的链路追踪。说起来比较晦涩,咱们看一个实例就明白了,在标准的微服务下日志产生的格式是:

2024-03-21 17:00:33.441 INFO [nio-7000-exec-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: b-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

但是当引入 Spring Cloud Sleuth 链路追踪组件后就会变成下面的格式

2024-03-21 17:00:33.441  INFO [a-service,5f70945e0eefa832,5f70945e0eefa832,true] 18404 --- [nio-7000-exec-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: b-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

//比较后会发现,在原有日志中额外附加了下面的文本

[a-service,5f70945e0eefa832,5f70945e0eefa832,true]

这段文本就是 Sleuth 在微服务日志中附加的链路调用数据,它的格式是固定的,包含以下四部分:

[微服务 Id,TraceId,SpanId,isExport]

我们来介绍一下这四部分的含义:

  • 微服务ID:指明日志是由哪个微服务产生的。

  • TraceId:轨迹编号。一次完整的业务处理过程被称为轨迹,例如:实现登录功能需要从服务 A 调用服务 B,服务B再调用服务 C,那这一次登录处理的过程就是一个轨迹,从前端应用发来请求到接收到响应,每一次完整的业务功能处理过程都对应唯一的 TraceId。

  • SpanId:步骤编号。刚才要实现登录功能需要从服务 A 到服务 C 涉及 3 个微服务处理,按处理前后顺序,每一个微服务处理时日志都被赋予不同的 SpanId。一个 TraceId 拥有多个 SpanId,而 SpanId 只能隶属于某一个 TraceId。

  • 导出标识:当前这个日志是否被导出,该值为 true 的时候说明当前轨迹数据允许被其他链路追踪可视化服务收集展现。

知道含义之后,我们来模拟一下上述业务逻辑执行的数据跟踪实例:

服务 A -> 服务 B -> 服务 C的调用链路,下面是分别产生的日志

#服务 A 应用控制台日志

2024-03-21 22:16:54.394 DEBUG [a-service,e8ca7047a782568b,e8ca7047a782568b,true] 21320 --- [nio-7000-exec-1] org.apache.tomcat.util.http.Parameters   : ...

#服务 B 应用控制台日志

2024-03-21 22:16:54.402 DEBUG [b-service,e8ca7047a782568b,b6aa80fb33e71de6,true] 21968 --- [nio-8000-exec-2] org.apache.tomcat.util.http.Parameters   : ...

#服务 C 应用控制台日志

2024-03-21 22:16:54.405 DEBUG [c-service,e8ca7047a782568b,537098c59827a242,true] 17184 --- [nio-9000-exec-2] org.apache.tomcat.util.http.Parameters   : ...

可以发现,在 DEBUG 级别下链路追踪数据被打印出来,按调用时间先后顺序分别是 A 到 C 依次出现。因为是一次完整业务处理,TraceId 都是相同的,SpanId 却各不相同,这些日志都已经被 Sleuth 导出,可以被 ZipKin 收集展示(ZipKin我们后面会聊到,感兴趣的记得关注哦)。

下面咱们通过实例讲解如何在微服务架构中进行链路追踪。

二、微服务整合Sleuth

1、创建微服务

创建 a-service、b-service、c-service 三个 Spring Boot 工程,pom.xml 依赖如下:

<!--Spring Web应用 -->

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-web</artifactId>

</dependency>

<!--Nacos 客户端 -->

<dependency>

    <groupId>com.alibaba.cloud</groupId>

    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

</dependency>

<!--服务间通信组件OpenFeign -->

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-openfeign</artifactId>

    <version>2.2.6.RELEASE</version>

</dependency>

c-service的pom.xml依赖如下:

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

    <groupId>com.alibaba.cloud</groupId>

    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

</dependency>

因为调用关系是服务 A 调用服务 B,服务 B 调用服务 C,所以在 A、B 两个服务中需要额外依赖 OpenFeign 实现服务间通信。

2、配置微服务的application.yml文件

server:

  port: 7000 #a:7000/b:8000/c:9000 

spring:

  cloud:

    nacos:

      discovery:

        server-addr: 106.14.221.171:8848

        username: nacos

        password: nacos

  application:

    name: a-service #a-service/b-service/c-service

logging:

  level:

    root: debug #为演示需要,开启debug级别日志

3、模拟业务逻辑

这里贴出来三个微服务的业务逻辑:

  • c-service:
SampleController,methodC方法产生响应字符串“-> Service C”,方法映射地址“/c”

@RestController

public class SampleController {

    @GetMapping("/c")

    public String methodC(){

        String result = " -> Service C";

        return result;

    }

}

  • b-service:
    CServiceFeignClient 通过 OpenFeign 实现了 C 服务的通信客户端,方法名为 methodC。
@FeignClient("c-service")

public interface CServiceFeignClient {

    @GetMapping("/c")

    public String methodC();

}

SampleController 通过 methodB 方法调用 methodC 的同时为响应附加的字符串“-> Service B”,方法映射地址“/b”。

@Controller

public class SampleController {

    @Resource

    private CServiceFeignClient cService;

    @GetMapping("/b")

    @ResponseBody

    public String methodB(){

        String result = cService.methodC();

        result = " -> Service B" + result;

        return result;

    }

}

  • a-service:
BServiceFeignClient通过OpenFeign实现了B服务的通信客户端,方法名为methodB

@FeignClient("b-service")

public interface BServiceFeignClient {

    @GetMapping("/b")

    public String methodB();

}

SampleController 通过 methodA 方法调用 methodB 的同时,成为响应附加的字符串“-> Service A”,方法映射地址“/a”。

@RestController

public class SampleController {

    @Resource

    private BServiceFeignClient bService;

    @GetMapping("/a")

    public String methodA(){

        String result = bService.methodB();

        result = "-> Service A" + result;

        return result;

    }

}

这样一个完整的调用链路已形成。在 3 个服务实例启动后,访问 A 实例

http://localhost:7000/a 得到运行结果

-> ServiceA -> Service B -> Service C

4、引入Sleuth

可以看到 ABC 三个服务按前后顺序依次产生结果,但目前在日志中并没有包含任何链路追踪数据,那如何引入 Sleuth 呢?
只需要打开三个服务工程的 pom.xml 文件分别引入 spring-cloud-starter-sleuth 依赖。

<!--添加Sleuth依赖 -->

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-sleuth</artifactId>

    <version>2.2.6.RELEASE</version>

</dependency>

加入依赖后,重启服务,无须做任何额外设置,Spring Cloud Sleuth 便自动为日志增加了链路追踪数据

#服务 A 应用控制台日志,已附加链路追踪数据

2024-03-21 22:16:54.394 DEBUG [a-service,e8ca7047a782568b,e8ca7047a782568b,true] 21320 --- [nio-7000-exec-1] org.apache.tomcat.util.http.Parameters   : ...

#服务 B 应用控制台日志

2024-03-21 22:16:54.402 DEBUG [b-service,e8ca7047a782568b,b6aa80fb33e71de6,true] 21968 --- [nio-8000-exec-2] org.apache.tomcat.util.http.Parameters   : ...

#服务 C 应用控制台日志

2024-03-21 22:16:54.405 DEBUG [c-service,e8ca7047a782568b,537098c59827a242,true] 17184 --- [nio-9000-exec-2] org.apache.tomcat.util.http.Parameters   : ...

虽然数据已产生,但如果在生产环境靠人工组织数以万计的链路日志显然不现实,我们还需要部署**链路追踪数据的分析工具 ZipKin **来简化这个过程。

ZipKin部署及使用,我们下篇文章再接着聊

文章将持续更新,欢迎关注公众号:服务端技术精选。欢迎点赞、关注、转发

相关推荐

  1. 分布式微服务架构日志调用跟踪-traceId

    2024-04-08 16:02:03       46 阅读
  2. 服务核心笔记】

    2024-04-08 16:02:03       32 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-08 16:02:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-08 16:02:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-08 16:02:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-08 16:02:03       18 阅读

热门阅读

  1. 室内设计专业MR混合现实情景实训教学系统应用

    2024-04-08 16:02:03       11 阅读
  2. 渗透测试漏洞之XSS漏洞

    2024-04-08 16:02:03       9 阅读
  3. Electron 是一个流行的框架

    2024-04-08 16:02:03       13 阅读
  4. 冶炼金属 二分法 十四届蓝桥杯省赛真题B组

    2024-04-08 16:02:03       15 阅读
  5. PostgreSQL Systemctl启动设置

    2024-04-08 16:02:03       13 阅读
  6. pycharm控制台中文显示乱码的解决方案

    2024-04-08 16:02:03       12 阅读
  7. vue watch监听的多种使用

    2024-04-08 16:02:03       16 阅读
  8. 面试反问环节

    2024-04-08 16:02:03       14 阅读