首页 > 其他分享 >分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】

时间:2023-12-13 12:32:09浏览次数:48  
标签:实战篇 Span 进阶 Trace Zipkin spring 链路 ID cloud


一、前言

我们在使用微服务的时候,往往设计到各个微服务之间的调用,肯定会存在深度的调用链路,如果出现BUG或者异常,就会让问题定位和处理效率非常低。
有了Sleuth ,就可以帮助我们记录、跟踪应用程序中的请求和操作。
通常与 Zipkin 配合使用,从而提供更全面的可视化应用程序跟踪和分析功能。

就像ElasticSearch和Kibana一样!

复杂的链路调用如下图所示:

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_spring boot

在继续往下看的同时,需要你具备Springboot整合Nacos构建一个聚合项目的能力。

当然如果不想自己来,小编也给大家准备好了。大家可以下载运行一下,开始下面的实战!

防止Github访问不了,这里把代码提交到了Gitee。

cloud-sleuth-zipkin-demo代码下载地址

二、Spring Cloud Sleuth 介绍

1. 简介

Spring Cloud Sleuth 是 Spring Cloud 生态系统的一部分,它是一个分布式追踪解决方案,用于监视微服务架构中的请求流程,并帮助开发者跟踪请求在不同微服务之间的传播路径。

Sleuth主要用于解决微服务架构中的分布式系统跟踪和调试问题。

官网文档

2. 核心概念

我们可以看一下官网的图片:

简单名词介绍:

cs客户端发送,客户已提出请求。该注释指示跨度的开始。
sr服务器已接收,服务器端收到请求并开始处理。从此时间戳中减去cs时间戳即可得出网络延迟。
ss服务器发送,在请求处理完成时(当响应发送回客户端时)进行注释。从这个时间戳中减去sr时间戳就可以得出服务器端处理请求所需的时间。
cr客户端已收到,表示跨度的结束。客户端已成功收到服务器端的响应。从此时间戳中减去cs时间戳即可得出客户端从服务器接收响应所需的整个时间。

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_spring_02

详细信息可以看官网介绍,总结一下:

名词

翻译

解释

Trace

追踪

Trace 是一个请求的整体追踪。它代表了从请求的起始点到结束点的完整路径,经过多个微服务。每个 Trace 都有一个唯一的 Trace ID。

Span

跨度

Span 是 Trace 中的一个小段,它代表了请求在某个特定微服务上的处理过程。Spans 之间有父子关系,它们可以形成一个层次结构,以表示请求的处理路径。

Trace ID

追踪标识

Trace ID 是唯一标识一个 Trace 的标识符。它在整个 Trace 中保持不变,用于将不同的 Span 关联到同一个 Trace 上。

Span ID

跨度标识

Span ID 是唯一标识一个 Span 的标识符。它用于在不同 Span 之间建立父子关系。

Parent Span ID

父 Span 标识

父 Span ID 是标识一个 Span 的父 Span 的标识符。它用于建立 Span 之间的关系。

Annotations

注解

Annotations 是关于 Span 的额外信息,通常用于记录 Span 的开始和结束时间、操作名称、以及其他相关信息。Annotations 可以帮助你更好地理解请求的处理过程。

Binary Annotations

二进制注解

Binary Annotations 是键值对形式的信息,用于记录与 Span 相关的自定义信息,例如请求的状态、错误信息等。

Collector

收集器

Collector 是用于收集追踪信息的组件,它将追踪数据发送到后端存储或可视化工具(如Zipkin或Jaeger)。Collector 可以将 Span 数据持久化,以供分析和监视使用。

Sampler

采样器

Sampler 用于确定是否对一个请求进行追踪。它决定是否为请求创建一个 Trace。Sampler 可以根据策略决定是否记录某个请求的 Trace 数据,以避免记录过多的追踪信息,从而降低性能开销。

官网的图,每一个代表一个组件,他们之间进行调用,画的少了Trace Id,加上就好了。

每个组件都会生成一个 Trace Id(全局唯一),还会有 Span Id、Parent Id 三部分组成。链路上的所有组件组成一个完整的 Trace。

注意:

头链路Parent Id = null,其余的都指向上一个组件的Span Id,从而形成链路。

一次链路调用所有的组件Trace Id都是一样的。

这里说的组件就是一个个的微服务!

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_分布式_03

三、 Zipkin介绍和搭建

1. 定义

Zipkin 是一个分布式追踪系统。它有助于收集解决服务架构中的延迟问题所需的计时数据。功能包括该数据的收集和查找。

Zipkin官网地址

2. 核心概念

名词

翻译

解释

Trace

追踪

Trace 代表整个请求的追踪路径,跨越不同的服务。

Span

跨度

Span 是基本工作单位,代表了请求在单个服务中的处理过程。

Trace ID

追踪标识

Trace ID 是唯一标识一个 Trace 的标识符,用于将不同的 Span 关联到同一个 Trace 上。

Annotations

注解

Annotations 用于记录 Span 的关键事件,通常包括开始和结束时间、操作名称等。

Binary Annotations

二进制注解

Binary Annotations 用于记录额外的自定义信息,例如请求状态、错误信息等。

Collector

收集器

Collector 负责接收和存储从不同服务发送的 Span 数据,以便后续的检查和分析。

Query and Visualization

查询和可视化

提供了查询和可视化界面,允许用户查看和分析跟踪数据,以帮助故障排查和性能优化。

尽管Sleuth 和 Zipkin有些术语和概念中有相似之处,但它们是两个不同的工具,各自有自己的实现和用途。

Spring Cloud Sleuth 用于生成和传播跟踪信息,而 Zipkin 用于收集、存储、查询和可视化这些信息。它们可以协同工作,但也可以独立使用。

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_ci_04

3. docker搭建

官方有三种方式搭建,推荐使用:如果您熟悉 Docker,这是首选的启动方法。

Docker Zipkin项目能够构建 docker 镜像、提供脚本和docker-compose.yml 用于启动预构建镜像的脚本。最快的启动方式是直接运行最新的镜像:

docker run -d -p 9411:9411 openzipkin/zipkin

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_spring boot_05

我们启动成功,在Windows下访问看是否成功!

http://192.168.239.130:9411/zipkin/

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_spring cloud_06

注意:

Zipkin默认将追踪数据信息保存到内存,重启服务后追踪数据丢失,Zipkin支持将追踪数据持久化到MySQL或ES。

可以直接使用docker-componse运行:

docker-componse运行脚本

可以自行试一下,这里就不带大家演示了!

四、Springboot整合

今天我们来进行简单的链路模拟:

service-order模块调用service-stock模块调用service-message模块

通信我们使用openFeign来进行调用,三个模块统一使用nacos进行注册

大家可以下载一下项目体验一下,可以自己搭建,就是一个聚合项目!

结构如下:

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_分布式_07

1. 导入依赖

这是父依赖

<properties>
    <spring.boot.version>2.7.3</spring.boot.version>
    <spring.cloud.dependencies.version>2021.0.1</spring.cloud.dependencies.version>
    <spring.cloud.alibaba.version>2021.0.1.0</spring.cloud.alibaba.version>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <org.projectlombok.lombok>1.18.26</org.projectlombok.lombok>
</properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring.boot.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>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${org.projectlombok.lombok}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

spring-cloud-dependencies里包含了sleuth、zipkin的依赖,父不需要在定义管理版本。

子依赖要比父依赖多了sleuth、zipkin两个,还有openFeign的包!

<!-- Sleuth依赖项 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

<!--Zipkin 依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>

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

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

2. yml配置

三份自己改一下端口和应用名称:service-order、service-stock、service-message;端口分别为:9000、9001、9002

server:
  port: 9000

spring:
  application:
    # 应用名称
    name: service-order
  cloud:
    nacos:
      discovery:
        # 服务注册地址
        server-addr: localhost:8848
  zipkin:
    base-url: http://192.168.239.130:9411
    sender:
      type: web # 设置使用 http 的方式传输数据

3. 详细代码

记得在启动类上添加注解:@EnableFeignClients,表示开启feign调用

完整的结构如下:

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_分布式_08


下面把具体代码给大家:

OrderController :

/**
 * @author wangzhenjun
 * @date 2023/10/31 14:25
 */
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/order")
@RestController
public class OrderController {

    private final RemoteStockFeignService remoteStockFeignService;
    /**
     * 模拟下单流程
     * @param userId
     * @param productId
     * @return
     */
    @GetMapping("/createOrder")
    public String createOrder(@RequestParam("userId") Integer userId, @RequestParam("productId") Integer productId) {
        log.info("====>订单模块<========");
        // 调用库存服务进行库存扣减
        String stockResult = remoteStockFeignService.subtractStock(userId,productId,1);
        log.info("扣减库存结果:{}", stockResult);
        // 还有其他。。。。。

        return "下单成功!";
    }
}

RemoteStockFeignService :

/**
 * @author wangzhenjun
 * @date 2023/10/31 14:29
 */
@FeignClient(value = "service-stock")
public interface RemoteStockFeignService {

    @GetMapping(value = "/stock/subtractStock")
    String subtractStock(@RequestParam(value = "userId") Integer userId,@RequestParam(value = "productId") Integer productId,@RequestParam(value = "num") Integer num);
}

StockController :

/**
 * @author wangzhenjun
 * @date 2023/10/31 14:40
 */
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/stock")
@RestController
public class StockController {

    private final RemoteMessageFeignService remoteMessageFeignService;

    @GetMapping(value = "/subtractStock")
    public String subtractStock(@RequestParam(value = "userId") Integer userId,@RequestParam(value = "productId") Integer productId, @RequestParam(value = "num") Integer num) {
        log.info("====>库存模块<========");
        if (productId < 1) {
            throw new RuntimeException("商品不存在,请重新请求!");
        }
        // 调用短信模块给用户发下单成功短信
        String messageResult = remoteMessageFeignService.sendMessage(userId);
        log.info("发送短信结果:{}", messageResult);
        return "扣减库存成功!";
    }
}

RemoteMessageFeignService:

/**
 * @author wangzhenjun
 * @date 2023/10/31 14:29
 */
@FeignClient(value = "service-message")
public interface RemoteMessageFeignService {

    @GetMapping(value = "/message/sendMessage/{userId}")
    String sendMessage(@PathVariable(value = "userId") Integer userId);
}

MessageController :

/**
 * @author wangzhenjun
 * @date 2023/10/31 14:40
 */
@Slf4j
@RequestMapping("/message")
@RestController
public class MessageController {


    @GetMapping(value = "/sendMessage/{userId}")
    public String sendMessage(@PathVariable(value = "userId") Integer userId) {
        log.info("====>短信模块<========");
        if (userId < 1 || userId > 999999) {
            throw new RuntimeException("用户不存在,请重新请求!");
        }
        return "发送短信成功!";
    }
}

4. 启动nacos

Windows下启动nacos,找到nacos下的bin目录执行命令:

startup.cmd -m standalone

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_分布式_09

找到地址,访问。用户名密码都是nacos。可以在配置文件中修改!

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_分布式_10

5. 注册成功

我们把三个模块进行启动!nacos上已经可以看到我们的服务注册上了,可以通过服务名进行调用了!

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_spring_11

五、调试

我们以订单模块为入扣进行链路调用:

http://localhost:9000/order/createOrder?userId=2&productId=89

1. 查看日志

我们看一下订单模块的日志。

可以总结出Sleuth 日志格式:

[service-order,e36ebe859a7473e7,e36ebe859a7473e7]

[服务名称,Trace ID,Span ID]

在最开始的链路上,Trace ID 和 Span ID 的值通常是相同的,这是因为它们都代表了整个请求的追踪。

一条链路使用一个相同的Trace ID。

在日志没有提现出Parent Span ID,不过不应该,我们可以通过Zipkin来看链路!

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_分布式_12

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_分布式_13

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_spring cloud_14

2. Zipkin查看

前面我们已经进入了Zipkin页面了,只需要刷新一下就可以看到每次链路的记录了!

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_ci_15

点击SHOW按钮,可以看到详细链路信息:

耗时,深度,Trance ID 还是挺好的。

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_spring_16

3. 模拟异常

我们来把商品修改一下:

http://localhost:9000/order/createOrder?userId=2&productId=-89

此时是库存服务出现的问题,就不会展示下一个消息模块,自然而然的找到了出现问题的链路和根源!

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_spring cloud_17

在模拟一个三级错误的,就会看到链路的最后一级!

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_ci_18


下面还可以查询依赖关系:

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_spring_19

点击节点,可以查看汇总,调用次数和失败次数的统计分析!

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】_ci_20

六、总结

分布式链路追踪已经成为现代微服务架构中不可或缺的工具之一。

通过它,我们可以清晰地跟踪请求的调用路径,了解系统的性能,诊断潜在问题,并不断优化我们的应用程序。

Spring Cloud Sleuth让我们轻松生成和传播跟踪信息,使我们的微服务能够协同工作,无缝地捕捉每个请求的处理路径。

Zipkin作为一个流行的分布式追踪系统,为我们提供了可视化界面,使我们能够以图形化的方式查看和分析跟踪数据。

当然简单系统上这个大材小用,但是我们可以在项目中试试,加了也不会影响程序的正常运行,做一个简单的知识储备!


看到这里了,还请动一下您的发财小手,关注一下公众号哈!!谢谢您的关注!!文章首发看!!!


标签:实战篇,Span,进阶,Trace,Zipkin,spring,链路,ID,cloud
From: https://blog.51cto.com/wangzhenjun/8800980

相关文章

  • 29-进阶SQL-索引分类
       思考题:第一个SQL语句效率要更高,这是因为id是通过聚集索引查询的,只需要一次查询就可以差点对应的数据。而第二个SQL语句是通过二级索引查询的,首先要根据name查询到对应的主键id,然后根据id再回表查询对应的数据。因此,哪怕id和name都有索引,也是id的聚集......
  • Kubernetes学习笔记——Kubernetes进阶
    一、深入理解Service1、Service存在的意义•防止Pod失联(服务发现)•定义一组Pod的访问策略(负载均衡)2、Pod与Service的关系•通过label-selector相关联•通过Service实现Pod的负载均衡(TCP/UDP4层)3、Service的三种类型-**ClusterIP**:集群内部使用,默认**,**分配一个稳定......
  • Redis进阶命令
    1.设置过期时间expire[keyName][seconds]eg:expirefoo60再次使用expire命令会重置键的过期时间。2.查看剩余过期时间ttl[keyName]eg:ttlfoottl表示timetolive3.使用事务连续执行一系列命令multi[command1][command2]...exec 4.排序可以对l......
  • 我的心血之作:一套适合 SAP UI5 从业人员从入门到进阶的学习教程,以及教程背后的故事
    一转眼2023年又要结束了。我从2007年开始,以软件开发工程师的角色进入职场,马上也快满17年了。在这快17年的软件开发职业生涯里,我也见识并使用了许许多多的开发技术,编程语言,开发框架,平台。IT界这十多年来涌现出的一些新技术,我也主动或被动地去追逐过。比如2015年时,大数据......
  • 27-进阶SQL-索引
    可以看到,上面的例子上,无索引的情况会查找全部的10次得到最终的结果,而有索引的情况会通过二叉排序树的数据结构,只需通过三次的查找就能得到最终的结果,更加的高效。(这里需要注意,上述二叉树索引结构只是一个示意图,并不是真实的索引结构) ......
  • 网络工程师-进阶提升课:华为HCIP Datacom认证介绍
    原创:厦门微思网络一、HCIP认证概述                                                                HCIP-DATACOM认证定位于中小型网络的构建和管理。HCIP-DATACOM认证包括但不限于:网络基础知识,交换机和路由......
  • 统筹高级前端,系统进阶精选案例实战,高效奠定前端基石
    前端开发是现代互联网行业中不可或缺的一环,随着前端技术的日新月异,前端工程师需要持续学习和进阶。本文将介绍一些高级前端开发的案例实战,旨在帮助读者高效地奠定前端基石。案例一:响应式布局在移动设备普及的今天,响应式布局已成为前端开发必备技能之一。通过使用媒体查询和流式布局......
  • 职场进阶,踏上高峰——HCIE-Datacom认证
    原创:厦门微思网络微思HCIE-Datacom课程介绍一、认证简介HCIE-Datacom(HuaweiCertifiedICTExpert-Datacom)认证是华为认证体系中的顶级认证,HCIE-Datacom认证定位具备坚实的企业网络跨场景融合解决方案理论知识,能够使用华为数通产品及解决方案进行企业园区网络、广域互联网络及广域......
  • ts01基础类型进阶
    ......
  • Python进阶补充
    变量的进阶引用的概念:1、定义变量的时候,变量和数据,都会在内存中开辟空间2、变量所对应的内存空间中存储的是数据所在内存的地址3、变量中保存数据地址的操作,就称为引用4、Python中所有数据的传递,都是引用,即“地址”5、只有赋......