什么是链路追踪?分布式系统如何实现链路追踪?

在分布式系统,尤其是微服务系统中,一次外部请求往往需要内部多个模块,多个中间件,多台机器的相互调用才能完成 。在这一系列的调用中,可能有些是串行的,而有些是并行的 。在这种情况下,我们如何才能确定这整个请求调用了哪些应用?哪些模块?哪些节点?以及它们的先后顺序和各部分的性能如何呢?
这就是涉及到链路追踪 。
什么是链路追踪?链路追踪是分布式系统下的一个概念,它的目的就是要解决上面所提出的问题,也就是将一次分布式请求还原成调用链路,将一次分布式请求的调用情况集中展示,比如,各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等等 。

什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
链路追踪的原理衡量一个接口,我们一般会看三个指标:
  1. 接口的 RT(Route-Target)你怎么知道?
  2. 接口是否有异常响应?
  3. 接口请求慢在哪里?
1、单体架构时代
在创业初期,我们的系统一般是单体架构,如下:
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
对于单体架构,我们可以使用 AOP(切面编程)来统计这三个指标,如下:
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
使用 AOP(切面编程),对原本的逻辑代码侵入更少,我们只需要在调用具体的业务逻辑前后分别打印一下时间即可计算出整体的调用时间 。另外,使用 AOP(切面编程)来捕获异常也可知道是哪里的调用导致的异常 。
2、微服务架构
随着业务的快速发展,单体架构越来越不能满足需要,我们的系统慢慢会朝微服务架构发展,如下:
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
一个稍微复杂的微服务架构
在微服务价格下,当有用户反馈某个页面很慢时,虽然我们知道这个请求可能的调用链是 A -----> C -----> B -----> D,但服务这么多,而且每个服务都有好几台机器,怎么知道问题具体出在哪个服务?哪台机器呢?
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
这也是微服务这种架构下的几个痛点:
  1. 排查问题难度大,周期长
  2. 特定场景难复现
  3. 系统性能瓶颈分析较难
分布式调用链就是为了解决以上几个问题而生,它主要的作用如下:
  1. 自动采取数据
  2. 分析数据,产生完整调用链:有了请求的完整调用链,问题有很大概率可复现
  3. 数据可视化:每个组件的性能可视化,能帮助我们很好地定位系统的瓶颈,及时找出问题所在
通过分布式追踪系统,我们能很好地定位请求的每条具体请求链路,从而轻易地实现请求链路追踪,进而定位和分析每个模块的性能瓶颈 。
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
3、分布式调用链标准(OpenTracing)
OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间 。它的出现是为了解决不同的分布式追踪系统 API 不兼容的问题 。
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
OpenTracing 通过提供与平台和厂商无关的 API,使得开发人员能够方便地添加追踪系统,就像单体架构下的AOP(切面编程)一样 。
说到这里,大家是否想过 JAVA 中类似的实现?还记得 JDBC 吧?JDBC 就是通过提供一套标准的接口让各个厂商去实现,程序员即可面对接口编程,不用关心具体的实现 。这里的接口其实就是标准 。所以,制定一套标准非常重要,可以实现组件的可插拔 。
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
OpenTracing 的数据模型,主要有以下三个:
  • Trace:一个完整请求链路
  • Span:一次调用过程(需要有开始时间和结束时间)
  • SpanContext:Trace 的全局上下文信息,如里面有traceId
为了让大家更好地理解这三个概念,我特意画了一张图:
什么是链路追踪?分布式系统如何实现链路追踪?

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


推荐阅读