在微服务开发中,一次服务的调用也许会涉及多个依赖服务和团队。当线上出现问题时,通常需要多个团队配合定位,排查问题需要的时间较长,涉及的人员较广,这样排查问题的效率很低。全链路追踪系统就是为了解决这些问题而开发,有了该系统,可以在发生故障时能够快速定位问题并解决问题。
最为开发人员所熟知的全链路追踪系统是谷歌公司的 Dapper。谷歌公司开发 Dapper 系统是为了收集复杂的分布式系统的行为信息,大部分开源的分布式链路追踪系统都是基于 Dapper 的基本原理开发的。本文主要讲解全链路追踪系统的基本概念与技术框架。
全链路追踪系统作为一个追踪监控系统,需要快速发现线上系统的故障,并能迅速定位故障位置,同时可以分析分布式系统中存在的性能瓶颈,从而辅助优化系统。这就要求全链路系统可以实时并全量地提供系统中的行为数据,做到高可用,并全面展现链路信息。
全链路追踪系统的设计目标主要包含以下几点:
通过上面列出的设计目标可知,全链路追踪系统的主要功能如下:
不同的开源链路追踪系统的设计虽然不同,但基本上都包括 Trace、Span、Tag 及采样率等几部分。下面将讲解全链路追踪系统中的一些常用概念。
Span是调用链中的一个基本单元。通常,一次服务调用会创建一个 Span,每个 Span 都有一个 ID 来标识,并且它在调用链中是唯一的。同时,Span 中还有其他信息,如描述信息、Tag 信息及父 Span id 等。
如图 1 所示为一个 Span 链路信息图。如果 Span 没有父 Span,则它是根 Span。通过 Span id 与 Parent id 可以查询整个链路中的Span。同时,每个 Span 都封装了很多信息,如操作描述信息、时间戳信息及键值对(Tag)信息。
通常,一个调用链会生成一条 Trace,由唯一的 Trace id 来标识。一条 Trace 可以由一个或多个 Span 组成,类似于树状结构,是一条调用链路,相当于一次完整的请求链路。
如图 2 所示,一条链路只有一个 Trace id,每个 Span 就是链路中的节点,节点之间的连线使 Span 与父节点 Span 发生联系,每个 Span中保存了一些请求信息。
Tag 用来描述 Span 中的一些特殊信息。在调用链的过程中,开发者如果需要保存一些特殊的业务信息,可以通过 Tag 设置键值对的方式进行保存。
线上环境对性能要求很高,如果对全部的请求都开启链路信息采集,会有一定的压力,因此可以通过设置采样率,在不牺牲大量性能的情况下进行信息采集,或者在某些关键时刻进行采集,便于定位线上问题。采样率可以设置全采样或某个速度进行采集。
全链路追踪系统已经是大型互联网应用程序的必备中间件,被广泛应用于监控系统或调用链追踪系统。现在有很多的开源全链路追踪系统供大家使用。下面我们讲解从开源的全链路追踪系统架构等方面介绍比较知名的调用链追踪工具。
Dapper 是谷歌公司内部的调用链追踪系统,该系统没有开源。谷歌公司在 2010 年发表了论文 Dapper, a Large-Scale Distributed Systems Tracing Infrastructure,其中定义了追踪数据的格式、追踪方式及调用链追踪系统的架构等理论模型。
大部分开源调用链追踪系统都是参照 Dapper 这篇论文提出的模型进行实现的。
如图 3 所示为 Dapper 收集数据的过程。Dapper 对谷歌公司内部的通用框架都提供了装配工具,服务部署了这些装配工具后就会对调用链进行追踪,装配工具将追踪信息保存到机器的磁盘上,每台服务器上部署的 Dapper daemon 会将追踪信息收集到 Dapper Collector上。
Dapper Collector 根据各个服务上报的追踪信息中包含的 traceId、spanId 和 parentSpanId 组装成完整的调用链,同时注明每个环节的耗时,然后进行存储并提供查询功能。
Zipkin 是 Twitter 公司按照 Dapper 论文中定义的追踪数据格式、追踪方式和架构进行了开发实现。Zipkin 主要包括 Collector、Storage和UI界面等组件,同时提供数据查询功能,如图 4 所示。
Zipkin 的整个架构与 Dapper 非常类似,它装配了追踪工具的服务:
其中,Transport 支持 HTTP、Kafka 等,Storage 存储支持 MySQL、Elasticsearch 和 Cassandra 等。Zipkin 的追踪是独立于开发语言的,只要满足 Zipkin 的追踪数据格式即可,它支持的框架包括 Grpc、Spring Web、Spring Boot 及 Spring Cloud 等。
Pinpoint 是韩国的搜索公司 Naver 基于 Google Dapper 开发的一款开源分布式调用链追踪系统。Pinpoint 对代码零侵入,运用了 Java Agent 字节码增强技术,只需要添加启动参数即可使用。
如图 5 所示,Pinpoint 框架的基本组成部分与 Zipkin 相似:
Pinpoint 使用字节码增强技术对服务进行埋点,追踪信息通过 Thrift 等方式上传到 Pinpoint Collector, Pinpoint 负责计算统计指标,并将实时结果和原始追踪信息都存入 HBase,前端 Web UI 从 HBase 中读数据进行展示查询。
Pinpoint 支持追踪的服务包括 Spring Boot、Thrift 和 Dubbo 等。它采用字节码增强技术侵入服务,业务无须修改代码,具有实时统计展示、JVM 实时监控及调用链追踪服务的特点。
Skywalking 是国内开源的一款调用链追踪系统。2019 年 4 月 17 日,SkyWalking 成为 Apache 的顶级项目,当前支持的开发语言包括Java、.NET 和 Node.js 等,数据存储支持 MySQL 和 Elasticsearch 等。
Skywalking 跟 Pinpoint 一样,采用字节码注入的方式实现代码的无侵入,支持云原生,目前增长势头强劲,其架构如图 6 所示。
Skywalking 在逻辑上包含 4 部分,分别是:
开源的全链路追踪系统从架构上看包括以下几个方面。
采集方式就是通常所说的埋点。埋点是调用链追踪系统与业务服务交互的部分,该部分需要做到低消耗与低侵入。Pinpoint 与 Skywalking开源组件采用了字节码增强技术,可以做到低侵入。追踪数据的上传有两种方式,即 HTTP 和 TCP。
此外,也可以通过日志采集方式进行追踪。Skywalking 的采集对吞吐量的影响比较小。
根据上传的追踪数据可以统计多维度指标,以了解服务的各种状态,如实时的 QPS、调用延时、延时分布、服务状态监控及服务依赖关系拓扑图等。
原始数据量比较大,一般存储在 HDFS、HBase、Elasticsearch 和 Cassandra 等分布式数据库中。统计报表类数据的数据量比较小,需要具有快速地按时间检索的能力,一般存储在 MySQL 或时序数据库中。
调用链追踪系统的数据最终通过UI界面展示,其中包含许多查询指标和调用链树形展示。Pinpoint界面的展示效果更加丰富,Zipkin的拓扑局限于服务与服务之间。
Spring Boot 2.x 提供了集成 Zipkin 的工具包,开发者可以很容易地在自己的业务工程里集成 Zipkin。下面介绍一下简单的集成示例。
(1)根据要求下载 zipkin-server 的 JAR 包,然后在本地启动 Zipkin 的 Server 实例,启动命令如下:
Java –jar zipkin-server.jar
(2)访问 http://localhost:9411/zipkin,即可打开 Zipkin 的 Web UI 页面,如图 7 所示。
(3)为本地服务添加 Zipkin 的相关依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
(4)在本地服务配置文件中添加 Zipkin 配置信息:
spring:
zipkin:
enabled: true
baseUrl: http://127.0.0.1:9411
sleuth:
sampler:
probability: 1
(5)启动本地服务,访问 http://localhost:8080/hi/springBoot,之后在 Zipkin 的管理页面中选择本地服务名,然后单击“查找”按钮,即可查找到刚才访问的 Trace 信息,如图 8 所示。
(6)单击信息即可进入详情页面,如图 9 所示。
图 9 展示了一次请求中 Zipkin 统计的信息,包括响应时间、http.method、http.path、mvc.controller.class、mvc.controller.method、traceId、spanId 和 parentId 等。
Pinpoint 与 Skywalking 都是使用 Agent 进行采集,其原理都是字节码增强技术。接下来将介绍 Skywalking 与 Spring Boot 的集成示例。具体步骤如下:
访问 https://www.apache.org/dyn/closer.cgi/skywalking/,选择 Skywalking 包,如果使用 Elasticsearch 7.x 版本,则需要下载相关的版本。本例选择不使用 Elasticsearch 包,版本是 8.0.1。
下载并解压后,目录包含以下几个部分:
添加 VM options 为:
-javaagent:E:\\apache-skywalking-apm-8.0.1\\apache-skywalking-apm-bin\\agent\\skywalking-agent.jar;
将环境变量设置为 W_AGENT_NAME=skywalking-test,然后启动本地服务,发送一次服务请求。