前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >10分钟带你彻底搞懂分布式链路跟踪

10分钟带你彻底搞懂分布式链路跟踪

原创
作者头像
写bug的高哈哈
发布2025-02-04 16:01:04
发布2025-02-04 16:01:04
1240
举报

在分布式系统中,我们基于业务划分服务,并对外暴露服务访问接口。在中大型系统中,可能需要很多个服务相互协同,才能完成一个接口功能。而随着业务的不断扩张,服务之间相互调用关系会越来越复杂。

分布式服务调用链路示意图
分布式服务调用链路示意图

从这张分布式服务调用链路的示意图中,你也可以看到,随着服务数量的不断增加,整个调用链路的分析工作变得越来越复杂。

显然,通过人工手段已经无法完成这种服务调用链路的分析。这时候,我们就需要引入分布式服务跟踪机制,并借助于一定的工具,来实现微服务架构下的服务监控。

分布式服务跟踪基本原理

首先,我们先来分析一下分布式服务跟踪机制的基本原理,这里,你需要先理解两个基本概念: Trace Id 和 Span Id。这两个概念是对服务跟踪最高层次的抽象,也是掌握分布式服务跟踪原理的基础

Trace Id 和 Span Id

  • Trace Id

Trace Id 即跟踪 ID。在分布式架构中,每个请求会生成一个全局的唯一性 ID,通过这个 ID 可以串联起整个调用链,也就是说请求在分布式系统内部流转时,系统需要始终保持传递该唯一性 ID,直到请求返回。这个唯一性 ID 就是 Trace Id。

  • Span Id

Trace Id 代表的是整个调用链路,而针对链路中的各个组成部分,我们也需要引入新的概念。所以,除了 Trace Id 外,我们还需要 Span Id。

Span Id 一般被称为跨度 ID。所谓跨度,就是调用链路中的一段时间,有明确的开始和结束这两个节点,这样通过计算开始时间和结束时间之间的时间差,我们就能明确调用过程在这个 Span 上所产生的时间延迟。

通过我刚才的介绍,相信你不难理解 Trace Id 和 Span Id 之间是一对多的关系,即在一个调用链路中只会存在一个 Trace Id,但会存在多个 Span Id。这样多个 Span Id 之间就会有父子关系,即链路中的前一个 Span Id 是后一个的父 Span Id。

Trace Id 和 Span Id 关系图
Trace Id 和 Span Id 关系图

四种注解

现在你理解了 Trace Id 和 Span Id 的概念。但这还不够,你可以想象在整个调用链路中,势必涉及到客户端与服务端之间的各种网络交互的请求处理过程,这些过程构成了完整调用链路中的各个环节。

所以,我们就要进一步拆分整个分布式调用链路,从而细化控制的粒度。业界一般通过四种不同的注解(Annotation)记录每个服务的客户端请求和服务器响应过程。

  • cs 注解

cs 代表 Client Send,即客户端发送请求,启动整个调用链路。

  • sr 注解

sr 代表 Server Received,即服务端接收请求。显然,(sr-cs)值代表请求从客户端到服务器端所需要的网络传输时间。

  • ss 注解

ss 代表 Server Send,即服务端把请求处理结果返回给客户端。(ss-sr)值代表服务器端处理该请求所需要的时间。

  • cr 注解

cr 代表 Client Received,即客户端接收到服务端响应,结束调用链路。(cr-ss)值代表响应结果从服务器端传输到客户端所需要的时间。

你可以结合这张示意图来进一步理解这四种注解之间的关联关系。

![请求和响应过程中的四种注解

](https://static001.geekbang.org/resource/image/96/34/96efb8df36ef0a12905b27753dd0ef34.png?wh=1101x483)

有了这四个注解之后,我们就可以使用它们来量化整个服务调用链路,从而找出潜在的问题。同样的,你可以看示意图辅助学习。

分布式调用链路中四种注解关联关系示意图
分布式调用链路中四种注解关联关系示意图

在这张图中,你可以看到,这次请求的 Trace Id 是 trace1,而 Span Id 根据不同的服务会发生变化,四种注解构成了客户端和服务器对一次请求处理的闭环。

对于服务 A 而言,cs 是 11:10:44,cr 是 11:10:55,也就说该次服务请求经由服务 A 的整个调用链路时间是 11s(11:10:44-11:10:55)。考虑到一半的响应时间都需要控制在 1~2s 之内,显然这个响应时间非常长。

分布式服务跟踪工具 Spring Cloud Sleuth

通过这些注解,我们就可以发现服务调用链路中存在的一系列问题,比方说前面提到的响应时间过长问题。而在日常开发过程中,我们也通常可以通过调用链路来发现,在本次请求过程中,某些服务发生的异常情况。

那么如何分析和解决这些问题呢?显然,在调用链路比较复杂的情况下,通过手动观测注解的方式不可行。这时候,我们就需要引入一些自动化工具。幸好,目前主流的服务监控实现工具都对这些注解做了支持和封装。

随着微服务架构的日益流行,Spring 自带的 Spring Cloud 应用也越来越广泛,目前已经成为这一领域的标准开发框架。所以,下面我们就基于 Spring Cloud 家族中的 Spring Cloud Sleuth(SCS)这款工具来分析具体的分布式链路跟踪使用方式。

对于分布式环境下的服务调用链路,我们可以通过 Spring Cloud Sleuth 完成两件事情:

  1. 服务调用链路的构建
  2. 服务监控数据的分析

使用 SCS 构建服务调用链路

首先,来看一看怎么实现用 SCS 构建服务调用链路。

通过将 Spring Cloud Sleuth 添加到系统的类路径,系统便会自动建立日志收集渠道。这些渠道不仅包括常见的 Spring MVC 控制器接收的 HTTP 请求,或者使用 RestTemplate 发出的请求,也能无缝支持通过 Zuul 网关发送的请求。

现在,假设我们有一个 UserService,那么通过 SCS 会生成类似这样的日志信息:

代码语言:txt
复制
INFO [userservice,81d66b6e43e71faa,6df220755223fb6e,true] 18100 --- [nio-8082-exec-8] c.s.user.controller.UserController : Get user by userName from 8082 port of userservice instance

我们关注于上述日志信息中如下所示的四段内容,即服务名称、Trace Id、Span Id 和 Zipkin 标志位:

代码语言:txt
复制
[服务名称, TraceId, SpanId, Zipkin标志位]

从日志信息的例子,你也能看到,

  • 第一段的,UserService,代表着该服务的名称。
  • 第二段中的 Trace Id,代表一次完整请求的唯一编号,例中的 81d66b6e43e71faa 就是该次请求的唯一编号。
  • 而第三段中的 6df220755223fb6e,就是这个 Trace Id 下的一个 Span Id。
  • 最后的第四段,代表 Zipkin 标志位,该标志位用于识别是否将服务跟踪信息同步到 Zipkin。

这里你或许会问 Zipkin 是什么,别着急,我们马上就要讲到。

到这里,服务调用链路就构建好了。那么我们如何监控数据呢?

使用 SCS 分析服务监控数据

针对监控数据的管理,你可以用 Spring Cloud Sleuth 设置常见的日志格式来输出 Trace Id 和 Span Id,也可以利用诸如 Logstash 等日志发布组件,将日志发布到 Elastic Search 等日志分析工具中进行处理。同时,Spring Cloud Sleuth 也兼容了 Zipkin、HTrace 等第三方工具的应用和集成。

在具体使用过程中,Spring Cloud Sleuth 和 Zipkin 是一个最佳组合,两者的兼容性非常好,集成过程也很简单。Zipkin 作为一款可视化工具,有其他工具所不具备的数据存储和可视化监控过程的优点。

接下来,我们就一起来看看,Zipkin 具体如何使用。

在结构上,Zipkin 包含几个核心的组件。其中,

  • 收集器组件,用来接收来自各个传输器的数据
  • 存储器代表存储组件,用来存储收集过来的数据
  • API 组件,提供简单的 RESTful API,负责查询存储器中存储的数据
  • UI 组件,提供简单的 Web 界面,可以方便而直观的查询和分析跟踪信息

对于服务监控而言,服务调用链数据收集、分析和管理的目的是,为了发现服务调用过程的问题,并采取相应的优化措施。

Zipkin 的最大优势在于提供了完整的可视化解决方案,通过它,你可以实现服务调用时序和服务调用数据的可视化。

这里我也展示了 Zipkin 可视化服务调用时序的主界面。

Zipkin 可视化服务调用时序的主界面
Zipkin 可视化服务调用时序的主界面

针对某个服务,Zipkin 的查询结果展示了包含该服务的所有调用链路,Zipkin 上的执行效果,你可以看一下。

当发起这个 HTTP 请求时,该请求会先到达网关服务 ZuulService,再通过路由转发到 UserService。图中最重要的就是各个 Span 信息。一个服务调用链路被分解成若干个 Span,每个 Span 代表完整调用链路中的一个可以衡量的部分。

通过可视化的界面,你可以看到整个访问链路的整体时长以及各个 Span 所花费的时间。每个 Span 的时延都已经被量化,并通过背景颜色的深浅来表示时延的大小。

在图中,我们点击任何一个感兴趣的 Span,就可以获取该 Span 对应的各项服务调用数据明细。

例如,我们点击“get /users/username/{username}”这个Span,Zipkin会跳转到一个新的页面并显示这样的数据。

Zipkin 中 Span 对应的名称、TraceId 和 SpanId
Zipkin 中 Span 对应的名称、TraceId 和 SpanId

这里,你可以看到本次调用中用于监控的最重要的元数据 Trace Id 和 Span Id。我们也可以进一步得到注解明细信息。

上图展示了针对该 Span 的 cs、sr、ss 和 cr 这四个注解数据。对于这个 Span 而言,ZuulService 相当于是 UserService 的客户端,所以 ZuulService 触发了 cs 事件,然后通过 (17.160 – 2.102)ms 到达了 UserService,以此类推。

从这些注解数据中可以得出一个结论,即该请求的整个服务响应时间主要取决于 UserService 自身的处理时间。如果这一处理时间过长,那么我们就可以有针对性的采取优化措施。

总结

可以说,构建服务监控和链路跟踪,在分布式系统开发过程中,是一项基础设施类工作。关于服务监控的基本原理其实并不复杂,业界也已经形成了一套比较统一的专业术语和方法论。而 Spring Cloud Sleuth 就是基于这些原理的一种具体实现工具。

Spring Cloud Sleuth 为我们提供了一种代码免侵入的整合方案,在多个服务进行交互的过程中,通过获取 Trace 和 Span 信息就能构建整个服务调用链路。同时,它还可以通过集成 Zipkin,提供可视化服务、调用时序、获取服务调用数据等强大功能。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分布式服务跟踪基本原理
    • Trace Id 和 Span Id
    • 四种注解
  • 分布式服务跟踪工具 Spring Cloud Sleuth
    • 使用 SCS 构建服务调用链路
    • 使用 SCS 分析服务监控数据
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档