1

几款符合 OpenTracing 规范的分布式链路追踪组件介绍与选型

 2 years ago
source link: http://blueskykong.com/2021/01/16/trace-consult/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

分布式链路追踪组件是在分布式架构中很重要的组件,用于排查分布式系统所遇到的问题。市面上有多款流行的分布式链路追踪组件,包括 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 来追踪微服务请求的细节。

学完本课时,关于分布式链路追踪的选型,你觉得哪一款分布式链路追踪组件适合你的业务场景,欢迎你在留言区和我分享。

Serverless 架构就不要服务器了?

微服务架构中使用 ELK 进行日志采集以及统一处理

如何使用 Prometheus 和 Grafana 监控预警服务集群?

订阅最新文章,欢迎关注我的公众号

微信公众号


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK