分布式链路追踪组件是在分布式架构中很重要的组件,用于排查分布式系统所遇到的问题。市面上有多款流行的分布式链路追踪组件,包括 Zipkin、Jaeger、Pinpoint 和 Skywalking 等,我们来了解下这几款组件的相关特性,以帮助我们选型。
分布式链路追踪规范:OpenTracing
Tracing 是在上世纪 90 年代就已出现的技术,但真正让该领域流行起来的还是源于 Google 的一篇 Dapper 论文。分布式追踪系统发展很快,种类繁多,但无论哪种组件,其核心步骤一般有 3 步:代码埋点、数据存储和查询展示,如下图所示为链路追踪组件的组成。
链路追踪组件的组成
目前流行的链路追踪组件有 Jaeger、Zipkin、Skywalking 和 Pinpoint 等。在数据采集过程中,对用户代码的入侵和不同系统 API 的兼容性,导致切换链路追踪系统需要巨大的成本。
为了解决不同的分布式追踪系统 API 不兼容的问题,诞生了 OpenTracing 规范。OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。OpenTracing 提供了 6 种语言的中立工具:Go、JavaScript、Java、Python、Objective-C 和 C ++。如下图所示为 OpenTracing 的架构。它支持 Zipkin、LightStep 和 Appdash 等追踪组件,并且可以轻松集成到开源的框架中,例如 gRPC、Flask、Django 和 Go-kit 等。
OpenTracing 架构
OpenTracing 是一个 Library 库,定义了一套通用的数据上报接口,要求各个分布式追踪系统都来实现这套接口。这样一来,应用程序只需要对接 OpenTracing,而无需关心后端采用的到底是什么分布式追踪系统,因此开发者可以无缝切换分布式追踪系统,也使得在通用代码库增加对分布式追踪的支持成为可能。
OpenTracing 于 2016 年 10 月加入 CNCF 基金会,是继 Kubernetes 和 Prometheus 之后,第三个加入 CNCF 的开源项目。它是一个中立的(厂商无关、平台无关)分布式追踪的 API 规范,提供统一接口,可方便开发者在自己的服务中集成一种或多种分布式追踪的实现。
几种流行的分布式链路追踪组件
在大家熟悉了分布式链路追踪中的一些基础概念之后,我们来具体了解一下这几种流行的分布式链路追踪组件。
简单易上手的 Twitter Zipkin
Zipkin 是一款分布式链路追踪组件,由 Twitter 开源,同样也兼容 OpenTracing API:它基于 Google Dapper 的论文设计,国内外很多公司都在用,文档资料也很丰富,其架构如下图所示。
Zipkin 架构图(来源 Zipkin 官网)
从 Zipkin 的架构图可知,Zipkin 包含如下 4 个部分:
- Collector:存储和索引报上来的链路数据,以供后续查找。
- Storage:Zipkin 的存储是可插拔的,最初是为了在 Cassandra 上存储数据而构建。除了 Cassandra,Zipkin 还原生支持 ElasticSearch 和 MySQL。
- Zipkin Query Service(API):一旦数据被存储和索引,我们就需要一种方法来查看它。Zipkin 搜索提供了一个简单的 JSON API,用于查找和检索 Trace 记录。此 API 的主要使用者是 Web UI。
- Web UI:Zipkin 查询链路追踪的界面。Web UI 提供了一种基于服务、时间和注解查看 Trace 记录的方法。
Zipkin 分布式链路监控的优势是语言无关性,整体实现较为简单。Zipkin 支持 Java、PHP、Go 和 NodeJS 等语言客户端。社区支持的插件较为丰富,包括 RabbitMQ、Mysql 和 HTTPClient 等(具体参见 https://github.com/openzipkin/brave/tree/master/instrumentation)。Zipkin UI 界面功能较为简单,本身无告警功能,可能需要二次开发。
云原生链路监控组件 Uber Jaeger
Jaeger 是 CNCF 云原生项目之一,Jaeger 受 Dapper 和 OpenZipkin 的启发,由 Uber 开源的分布式追踪系统,兼容 Open Tracing API。它用于微服务的监控和排查,支持分布式上下文传播、分布式事务的监控、报错分析、服务的调用网络分析以及性能/延迟优化。Jaeger 的服务端使用 Go 语言实现,其存储支持 Cassandra、Elasticsearch 和内存,并提供了 Go、Java、Node、Python 和 C++ 等语言的客户端库。Jaeger 具有如下的特性:
- 高扩展性 Jaeger 后端的分布式设计,可以根据业务需求进行扩展。例如,Uber 任意一个 Jaeger 每天通常要处理数十亿个跨度。
- 原生支持 OpenTracing
Jaeger 后端、Web UI 和工具库的设计支持 OpenTracing 标准。
- 通过跨度引用将轨迹表示为有向无环图(不仅是树)
- 支持强类型的跨度标签和结构化日志
- 通过行李支持通用的分布式上下文传播机制
- 支持多个存储后端 Jaeger 支持两种流行的开源 NoSQL 数据库作为跟踪存储后端:Cassandra 3.4+ 和 Elasticsearch 5.x / 6.x。
- 现代化 Web UI Jaeger Web UI 是使用流行的开源框架实现的。v1.0 中发布了几项性能改进,以允许 UI 有效处理大量数据,并能够显示上万跨度的链路跟踪。
- 支持云原生部署 Jaeger 后端支持 Docker 镜像部署。二进制文件支持各种配置方法,包括命令行选项,环境变量和多种格式(yaml、toml 等)的配置文件。可以方便地部署到 Kubernetes 集群。
- 可观察性 默认情况下,所有 Jaeger 后端组件均开放 Prometheus 监控(也支持其他指标后端)。使用结构化日志库 zap 将日志标准输出。
- 与 Zipkin 向后兼容 已经使用 Zipkin 库,如果我们要切换到 Jaeger,客户端也不必重写所有代码。Jaeger 通过在 HTTP 上接受 Zipkin 格式(Thrift 或 JSON v1 / v2)的跨度来提供与 Zipkin 的向后兼容性。从 Zipkin 后端切换到 Jaeger 后端变得很简单。
Jaeger 的架构如下图所示。
Jaeger 架构图
我们来分析一下 Jaeger 的架构图,Jaeger 主要由以下几部分组成:
- jaeger client:为不同语言实现了符合 OpenTracing 标准的 SDK。应用程序通过 API 写入数据,client library 把 trace 记录按照应用程序指定的采样策略传递给 jaeger-agent。
- jaeger-agent:它是一个监听在 UDP 端口上用以接收 span 数据的网络守护进程,它会将数据批量发送给 collector。它被设计成一个基础组件,部署到所有的宿主机上。jaeger-agent 将 client library 和 collector 解耦,为 client library 屏蔽了路由和发现 collector 的细节。
- jaeger-collector:接收 jaeger-agent 发送来的数据,然后将数据写入后端存储。jaeger-collector 被设计成无状态的组件,因此可以同时运行任意数量的 jaeger-collector。
- Data Store:后端存储被设计成一个可插拔的组件,支持将数据写入 Cassandra、Elastic Search。
- jaeger-query:接收查询请求,然后从后端存储系统中检索 trace 并通过 UI 进行展示。jaeger-query 是无状态的,我们可以启动多个实例,把它们部署在 Nginx 这样的负载均衡器后面。
下图为 Jaeger UI 中的统计视图,还可以点击进去查看请求的链路调用详情。
Jaeger 链路监控页面
列表中展示了请求的追踪记录,每次请求的时间、涉及的服务名和 Span 数量。通过统计的散列图,可以很清楚地看到请求的响应时间分布。相比于 Zipkin,Jaeger 在界面上较为丰富,但是也无告警功能。
SkyWalking
SkyWalking 是一个国产的 APM 开源组件,具有监控、跟踪和诊断云原生架构中分布式系统的功能。SkyWalking 支持多个来源和多种格式收集 Trace 和 Metric 数据,包括:
- Java、.NET Core、NodeJS 和 PHP 语言自动织入的 SkyWalking 格式
- 手动织入的 Go 客户端 SkyWalking 格式
- Istio 追踪的格式
- Zipkin v1/v2 格式
- Jaeger gRPC 格式
SkyWalking 的核心是数据分析和度量结果的存储平台,通过 HTTP 或 gRPC 方式向 SkyWalking Collecter 提交分析和度量数据。SkyWalking Collecter 对数据进行分析和聚合,并存储到数据库。最后我们可以通过 SkyWalking UI 的可视化界面对最终的结果进行查看。SkyWalking 支持从多个来源和多种格式收集数据:多种语言的 Skywalking Agent、Zipkin v1/v2、Istio 勘测、Envoy 度量等数据格式。
如下图所示为 SkyWalking 6.x 的架构图。SkyWalking 整体架构的模块较多,但是结构比较清晰,主要就是通过收集各种格式的数据进行存储,然后展示。
SkyWalking 6.x 架构图
SkyWalking 支持的存储组件有:ES、H2、Mysql、TiDB 和 Sharding Sphere。SkyWalking 的 UI 界面提供的链路追踪查询较为简单,SkyWalking 拥有非常活跃的中文社区,支持多种语言的探针,且对国产开源软件全面支持。SkyWalking 在探针性能方面表现优异,根据官方提供的基准测试结果,SkyWalking 探针的性能损耗较低。
链路统计详细的 Pinpoint
Pinpoint 是一个 APM 工具,适用于用 Java/PHP 编写的大型分布式系统,Go 语言项目不能直接应用 Pinpoint,如需使用则需要使用代理进行改造。这里简单进行介绍,因为其链路追踪的分析较为完善。Pinpoint 也是受 Dapper 的启发,可以通过跟踪分布式应用程序之间的调用链,帮助分析系统的整体结构以及它们中的组件是如何相互连接,如下图所示。
Pinpoint 链路监控页面
Pinpoint 的追踪数据粒度非常细,用户界面功能强大,Pinpoint 中的服务调用展示做得非常丰富,在这方面它优于市面上大多数组件。Pinpoint 使用 HBase 作为存储带 来了海量存储的能力。丰富的数据背后,必然需要大量的数据采集,因此在几款常用链路追踪组件中,Pinpoint 的探针性能最低,在生产环境需要注意应用服务的采样率,过高会影响系统的吞吐量。
另外,Pinpoint 目前仅支持 Java 和 PHP 语言,采用字节码增强方式去埋点,所以在埋点时不需要修改业务代码,是非侵入式的,非常适合项目已经完成之后再增加调用链监控的实践场景。Pinpoint 并不支持除 Java、PHP 语言之外的探针,在 Go 语言项目中应用需要基于 Pinpoint 进行二次封装开发。
4 种分布式链路追踪组件的指标对比
如上几个小节对 4 种当前流行的链路追踪组件进行了简单介绍,我们对每个组件的组成和特性有了大概的了解,下面我们将根据如下的几个指标对它们进行直观的对比。
指标/组件 | Zipkin | Jaeger | Skywalking | Pinpoint |
---|---|---|---|---|
OpenTracing 兼容 | 支持 | 支持 | 支持 | 不支持 |
客户端支持语言 | Java、C#、Go、PHP 等 | Java、C#、Go、PHP 等 | Java, .NET Core, NodeJS and PHP | Java、PHP |
传输协议 | Http/MQ | UDP/Http | gRPC | Thrift |
Web UI | 弱 | 一般 | 一般 | 强 |
扩展性 | 强 | 强 | 一般 | 弱 |
性能损失 | 一般 | 一般 | 低 | 高 |
实现方式 | 拦截请求,侵入 | 拦截请求,侵入 | 字节码注入,无侵入 | 字节码注入,无侵入 |
告警 | 不支持 | 不支持 | 支持 | 支持 |
可以看出,Zipkin 和 Jaeger 在各个方面都差不多,Jaeger 是在 Zipkin 的基础上改进了 Web UI 和传输协议等方面且支持更多的客户端语言。SkyWalking 相对前面两种组件来说,功能较为齐全,探针性能损耗低,同时也支持多种语言的客户端。Pinpoint 在 Web UI 的丰富性上完胜其他三种,然而其不支持 Go 语言客户端,实际应用需要进行改造,除此之外性能和可扩展性方面的不足值得我们在选型时考虑权衡。每种组件都有其优势和劣势,笔者建议在链路追踪组件的选型时,根据自身业务系统的实际情况,哪些不能妥协,哪些可以舍弃,从而更好的选择一款最适合的组件。
当然,除了通过修改应用程序代码增加分布式追踪之外,还有一种不需要修改代码的非入侵的方式,那就是 Service Mesh。Service Mesh 在网络层面拦截,通过 Sidecar(Sidecar 主张以额外的容器来扩展或增强主容器,而这个额外的容器被称为 Sidecar 容器)的方式为各个微服务增加一层代理,通过这层网络代理来实现一些服务治理的功能,因为是工作在网络层面,可以做到跨语言、非入侵。
小结
本文主要介绍了分布式链路追踪的 OpenTracing 规范,以及几种常见的分布式链路追踪组件选型。通过在 Go 语言中通过修改应用程序代码增加分布式追踪。这种方式有一定的侵入性,但也是目前使用最多的分布式链路追踪方式。接下来的内容我们将进入实践环节,通过一个案例演示如何应用 Zipkin 来追踪微服务请求的细节。
学完本课时,关于分布式链路追踪的选型,你觉得哪一款分布式链路追踪组件适合你的业务场景,欢迎你在留言区和我分享。