微服务监控之分布式链路追踪技术

分布式链路追踪技术核心思想

本质:记录日志,作为一个完整的技术,分布式链路追踪也有自己的理论和概念
为了追踪整个调用链路,肯定需要记录日志,日志记录是基础
image.png
image.png

上图标识请求链路,一条链路通过TraceId唯一标识,span标识发起的请求信息,各span通过 parrentId关联起来。
Trace:服务追踪的追踪单元是从客户发起请求(request)抵达被追踪系统的边界开始,到被追踪系统向客户返回响应(response)为止的过程

Trace ID:为了实现请求跟踪,当请求发送到分布式系统的入口端点时,只需要服务跟踪框架为该请求创建一个唯一的跟踪标识Trace ID,同时在分布式系统内部流转的时候,框架失踪保持该唯一标识,直到返回给请求方,一个Trace由一个或者多个Span组成,每一个Span都有一个SpanId,Span中会记录 TraceId,同时还有一个叫做ParentId,指向了另外一个Span的SpanId,表明父子关系,其实本质表达了依赖关系

Span ID:为了统计各处理单元的时间延迟,当请求到达各个服务组件时,也是通过一个唯一标识Span ID来标记它的开始,具体过程以及结束。对每一个Span来说, 它必须有开始和结束两个节点,通过记录开始Span和结束Span的时间戳,就能统计出该Span的时间延迟,除了时间戳记录之外,它还可以包含一些其他元数据,比如时间名称、请求信息等。 每一个Span都会有一个唯一跟踪标识 Span ID,若一个有序的 span 就组成了一个 trace。

Span可以认为是一个日志数据结构,在一些特殊的时机点会记录了一些日志信息, 比如有时间戳、spanId、TraceId,parentIde等,Span中也抽象出了另外一个概 念,叫做事件,核心事件如下

image.png

耗时分析:通过 Sleuth 了解采样请求的耗时,分析服务性能问题(哪些服务调用比较耗时)
链路优化:发现频繁调用的服务,针对性优化等 Sleuth就是通过记录日志的方式来记录踪迹数据的

注意:把Spring Cloud Sleuth 和 Zipkin 一起使用,把Sleuth的数据信息发送给Zipkin进行聚合,利用 Zipkin 存储并展示数据

image.png

Sleuth + Zipkin 的使用

1、需要追踪的服务引入依赖(Sleuth)

每一个需要被追踪踪迹的微服务工程都引入依赖坐标

  1. <!--链路追踪-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-sleuth</artifactId>
  5. </dependency>

2、服务配置文件需增加日志级别

在控制台可以观察到 Sleuth 输出的日志(全局 TraceId、SpanId 等),但是不容易阅读观察,另外⽇志分散在各个微服务服务器上

  1. logging:
  2. level:
  3. # Feign日志只会对日志级别为debug的做出响应
  4. com.lagou.edu.controller.service.ResumeServiceFeignClient: debug
  5. org.springframework.web.servlet.DispatcherServlet: debug
  6. org.springframework.cloud.sleuth: debug

3、结合 Zipkin 展示追踪数

Zipkin 包括Zipkin Server和 Zipkin Client两部分,Zipkin Server是一个单独的服务,Zipkin Client就是具体的微服务。(要求被追踪的各个微服务都需要添加Zipkin Client)

Zipkin Server 构建(S)

  1. <!--zipkin-server的依赖坐标-->
  2. <dependency>
  3. <groupId>io.zipkin.java</groupId>
  4. <artifactId>zipkin-server</artifactId>
  5. <version>2.12.3</version>
  6. <exclusions>
  7. <!--排除掉log4j2的传递依赖,避免和springboot依赖的日志组件冲突-->
  8. <exclusion>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-log4j2</artifactId>
  11. </exclusion>
  12. </exclusions>
  13. </dependency>
  14. <!--zipkin-server ui界面依赖坐标-->
  15. <dependency>
  16. <groupId>io.zipkin.java</groupId>
  17. <artifactId>zipkin-autoconfigure-ui</artifactId>
  18. <version>2.12.3</version>
  19. </dependency>

启动类开启Zipkin Server功能 (S)

  1. @SpringBootApplication
  2. @EnableZipkinServer // 开启Zipkin 服务器功能
  3. public class ZipkinServerApplication9411 {
  4. public static void main(String[] args) {
  5. SpringApplication.run(ZipkinServerApplication9411.class,args);
  6. }
  7. }

添加配置文件application.yml(S)

  1. server:
  2. port: 9411
  3. management:
  4. metrics:
  5. web:
  6. server:
  7. auto-time-requests: false # 关闭自动检测

Zipkin Client 构建(C)

( 在具体微服务中修改, 在pom中添加 zipkin 依赖 )

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-zipkin</artifactId>
  4. </dependency>

配置文件添加对zipkin server的引用(C)

改客户端微服务是lagou-service-autodeliver-8096,对应的服务名称是lagou-service-autodeliver

  1. spring:
  2. application:
  3. name: lagou-service-autodeliver
  4. zipkin:
  5. base-url: http://127.0.0.1:9411 # zipkin server的请求地址
  6. sender:
  7. # web 客户端将踪迹日志数据通过网络请求的方式传送到服务端,另外还有配置
  8. # kafka/rabbit 客户端将踪迹日志数据传递到mq进行中转
  9. type: web
  10. sleuth:
  11. sampler:
  12. # 采样率 1 代表100%全部采集 ,默认0.1 代表10% 的请求踪迹数据会被采集
  13. # 生产环境下,请求量非常大,没有必要所有请求的踪迹数据都采集分析,对于网络包括server端压力都是比较大的,可以配置采样率采集一定比例的请求的踪迹数据进行分析即可
  14. probability: 1

另外,对于log日志,依然保持开启debug状态
Zipkin server 页面方便我们查看服务调用依赖关系及一些性能指标和异常信息

追踪数据Zipkin持久化到mysql (S)

mysql中创建名称为zipkin的数据库,并执行如下sql语句(官方提供)

需要创建zipkin的数据库

pom中引入相关依赖

  1. <!--zipkin针对mysql持久化的依赖-->
  2. <dependency>
  3. <groupId>io.zipkin.java</groupId>
  4. <artifactId>zipkin-autoconfigure-storage-mysql</artifactId>
  5. <version>2.12.3</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>mysql</groupId>
  9. <artifactId>mysql-connector-java</artifactId>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.alibaba</groupId>
  13. <artifactId>druid-spring-boot-starter</artifactId>
  14. <version>1.1.10</version>
  15. </dependency>
  16. <!--操作数据库需要事务控制-->
  17. <dependency>
  18. <groupId>org.springframework</groupId>
  19. <artifactId>spring-tx</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework</groupId>
  23. <artifactId>spring-jdbc</artifactId>
  24. </dependency>

ZipkinServer配置文件添加数据连接(S)

添加链接数据库的配置信息

  1. spring:
  2. datasource:
  3. driver-class-name: com.mysql.jdbc.Driver
  4. url: jdbc:mysql://localhost:3306/zipkin?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
  5. username: root
  6. password: 123456
  7. druid:
  8. initialSize: 10
  9. minIdle: 10
  10. maxActive: 30
  11. maxWait: 50000
  12. # 指定zipkin持久化介质为mysql
  13. zipkin:
  14. storage:
  15. type: mysql

启动类中注入事务管理器(S)

  1. // 注入事务控制器
  2. @Bean
  3. public PlatformTransactionManager transactionManager(DataSource dataSource) {
  4. return new DataSourceTransactionManager(dataSource);
  5. }

zipkin-server 完整的配置信息

  1. server:
  2. port: 9411
  3. management:
  4. metrics:
  5. web:
  6. server:
  7. auto-time-requests: false # 关闭自动检测
  8. spring:
  9. datasource:
  10. driver-class-name: com.mysql.jdbc.Driver
  11. url: jdbc:mysql://localhost:3306/zipkin?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
  12. username: root
  13. password: 123456
  14. druid:
  15. initialSize: 10
  16. minIdle: 10
  17. maxActive: 30
  18. maxWait: 50000
  19. # 指定zipkin持久化介质为mysql
  20. zipkin:
  21. storage:
  22. type: mysql

zipkin-server 完整的启动类信息

  1. @SpringBootApplication
  2. @EnableZipkinServer // 开启Zipkin 服务器功能
  3. public class ZipkinServerApplication9411 {
  4. public static void main(String[] args) {
  5. SpringApplication.run(ZipkinServerApplication9411.class,args);
  6. }
  7. // 注入事务控制器
  8. @Bean
  9. public PlatformTransactionManager transactionManager(DataSource dataSource) {
  10. return new DataSourceTransactionManager(dataSource);
  11. }
  12. }

完整的思路是:引入坐标、开启功能、添加事物、添加数据连接等。