专栏名称: 芋道源码
纯 Java 源码分享公众号,目前有「Dubbo」「SpringCloud」「Java 并发」「RocketMQ」「Sharding-JDBC」「MyCAT」「Elastic-Job」「SkyWalking」「Spring」等等
51好读  ›  专栏  ›  芋道源码

40 张图搞懂分布式日志追踪,强大的traceId

芋道源码  · 公众号  · Java  · 2025-03-17 09:27

正文

👉 这是一个或许对你有用 的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入 芋道快速开发平台 知识星球。 下面是星球提供的部分资料:

👉 这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、CRM 等等功能:

  • Boot 仓库:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 仓库:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本

来源:码海


前言

在微服务架构中,一次请求往往涉及到多个模块,多个中间件,多台机器的相互协作才能完成。这一系列调用请求中,有些是串行的,有些是并行的,那么如何确定这个请求背后调用了哪些应用,哪些模块,哪些节点及调用的先后顺序?如何定位每个模块的性能问题?本文将为你揭晓答案。

本文将会从以下几个方面来阐述

  • 分布式追踪系统原理及作用
  • SkyWalking的原理及架构设计
  • 我司在分布式调用链上的实践

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

分布式追踪系统的原理及作用

如何衡量一个接口的性能好坏,一般我们至少会关注以下三个指标

  • 接口的 RT 你怎么知道?
  • 是否有异常响应?
  • 主要慢在哪里?

单体架构

在初期,公司刚起步的时候,可能多会采用如下单体架构,对于单体架构我们该用什么方式来计算以上三个指标呢?

最容易想到的显然是用 AOP

使用 AOP 在调用具体的业务逻辑前后分别打印一下时间即可计算出整体的调用时间,使用 AOP 来 catch 住异常也可知道是哪里的调用导致的异常。

微服务架构

在单体架构中由于所有的服务,组件都在一台机器上,所以相对来说这些监控指标比较容易实现,不过随着业务的快速发展,单体架构必然会朝微服务架构发展,如下

如图示:一个稍微复杂的微服务架构

如果有用户反馈某个页面很慢,我们知道这个页面的请求调用链是 A ----->  C ----->  B ----->  D,此时如何定位可能是哪个模块引起的问题。每个服务 Service A,B,C,D 都有好几台机器。怎么知道某个请求调用了服务的具体哪台机器呢?

可以明显看到,由于无法准确定位每个请求经过的确切路径,在微服务这种架构下有以下几个痛点

  1. 排查问题难度大,周期长
  2. 特定场景难复现
  3. 系统性能瓶颈分析较难

分布式调用链就是为了解决以上几个问题而生,它主要的作用如下

  • 自动采取数据
  • 分析数据产生 完整调用链 :有了请求的完整调用链,问题有很大概率可复现
  • 数据可视化:每个组件的性能可视化,能帮助我们很好地定位系统的瓶颈,及时找出问题所在

通过分布式追踪系统能很好地定位如下请求的每条具体请求链路,从而轻易地实现请求链路追踪,每个模块的性能瓶颈定位与分析。

分布式调用链标准 - OpenTracing

知道了分布式调用链的作用,那我们来看下如何实现分布式调用链的实现及原理, 首先为了解决不同的分布式追踪系统 API 不兼容的问题,诞生了 OpenTracing 规范,OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。

这样 OpenTracing 通过提供平台无关,厂商无关的 API,使得开发人员能够方便地添加追踪系统的实现。

说到这大家是否想过 Java 中类似的实现?还记得 JDBC 吧,通过提供一套标准的接口让各个厂商去实现,程序员即可面对接口编程,不用关心具体的实现。这里的接口其实就是标准,所以制定一套标准非常重要,可以实现组件的可插拔。

接下来我们来看 OpenTracing 的数据模型,主要有以下三个

  • Trace :一个完整请求链路
  • Span :一次调用过程(需要有开始时间和结束时间)
  • SpanContext :Trace 的全局上下文信息, 如里面有traceId

理解这三个概念非常重要,为了让大家更好地理解这三个概念,我特意画了一张图

如图示,一次下单的 完整请求 完整就是一个 Trace, 显然对于这个请求来说,必须要有一个全局标识来标识这一个请求,每一次调用就称为一个 Span,每一次调用都要带上全局的 TraceId, 这样才可把全局 TraceId 与每个调用关联起来,这个 TraceId 就是通过 SpanContext 传输的,既然要传输显然都要遵循协议来调用。如图示,我们把传输协议比作车,把 SpanContext 比作货,把 Span 比作路应该会更好理解一些。

理解了这三个概念,接下来我看看分布式追踪系统如何采集统一图中的微服务调用链

我们可以看到底层有一个 Collector 一直在默默无闻地收集数据,那么每一次调用 Collector 会收集哪些信息呢。

  1. 全局 trace_id:这是显然的,这样才能把每一个子调用与最初的请求关联起来
  2. span_id: 图中的 0,1,1.1,2,这样就能标识是哪一个调用
  3. parent_span_id:比如 b 调用 d 的  span_id 是 1.1,那么它的 parent_span_id 即为 a 调用 b 的 span_id 即 1,这样才能把两个 紧邻的调用 关联起来。

有了这些信息,Collector 收集的每次调用的信息如下

根据这些图表信息显然可以据此来画出调用链的可视化视图如下

于是一个完整的分布式追踪系统就实现了。

以上实现看起来确实简单,但有以下几个问题需要我们仔细思考一下

  1. 怎么 自动 采集 span 数据:自动采集,对业务代码无侵入
  2. 如何跨进程传递 context
  3. traceId 如何保证全局唯一
  4. 请求量这么多采集会不会影响性能

接下我来看看 SkyWalking 是如何解决以上四个问题的

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

SkyWalking的原理及架构设计

怎么自动采集 span 数据

SkyWalking 采用了







请到「今天看啥」查看全文