随着微服务生态的盛行,在基于不同的业务场景中,一个简单的请求往往可能会涉及到多个不同服务类型,此时,若某个服务所提供的业务出现异常,从而可能会导致整个业务处理链路中的问题跟踪、定位及其分析较为困难,服务之间的依赖梳理、组件排查就变得尤为复杂。
因此,在实际的生产业务场景中,为了能够全方位地追踪每一个相关组件的行为轨迹,就需要一些能够可以帮助我们理解、追踪系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和暴露问题之间的相关关键点,从而高效地解决问题。基于上述痛点,此时,APM 系统便应运而生。
APM 全称为 Application Performance Monitor。在此生态领域中,首先且必须要提的便是全球技术老大哥:Google。毕竟,AMP 最早是谷歌公开的论文提到的 Google Dapper。Dapper 是 Google 生产环境下的分布式跟踪系统。基于此系统,使得 Google 的开发和运维等技术团队在业务场景中能够针对问题的定位与分析达到事半功倍的效果,省时省力。自此, Dapper 开始发展成为“服务调用”的一流监控系统鼻祖。开启了服务链路追踪生态系统的篇章。
从本质上讲,APM 就是跟踪一个 TraceId 在多个微服务中信息的传递及记录。在进入第一个服务的时候,就会生成一个 TraceId,此时,在接下来链路中,此 TraceId 将跟随整个微服务调用链,一直到整个调用链的结束, 因此,我们只需要分析此 TraceId 所记录的服务和时间, 就能够知道请求(入口服务)在哪个环节(哪些服务)耗费多少时间, 总的耗费时间。基于广义角度而言,一个 Trace 代表了一个事务或者流程在(分布式)系统中的执行过程。Trace 是多个 Span 组成的一个有向无环图(DAG),每一个 Span 代表 Trace 中被命名并计时的连续性的执行片段,具体如下图所示:
一个 Tracer 过程中,各 Span 之间的关系 [Span A] ←←←(the root span) | +------+------+ | | [Span B] [Span C] ←←←(Span C 是 Span A 的子节点, ChildOf) | | [Span D] +---+-------+ | | [Span E] [Span F] >>> [Span G] >>> [Span H] ↑ ↑ ↑ (Span G 在 Span F 后被调用, FollowsFrom)
Ttracer 与 Span 的时间轴关系 ––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time [Span A···················································] [Span B··············································] [Span D··········································] [Span C········································] [Span E·······] [Span F··] [Span G··] [Span H··]
例如,在基于 Jaeger 分布式链路追踪系统中,一个 Span 表示 Jaeger 的逻辑工作单元,Span 具有操作名称,操作的开始时间,和持续时间。Span 可以嵌套并排序以建立因果关系模型。
在 Jaeger 之前,其实较为流行的非 Zipkin 莫属,毕竟,其受于谷歌 Dapper 论文启发,由 Twitter 团队开发维护并开源。Jaeger 由 Uber 公司研发并开源,其实现遵循的是 “ OpenTracing 规范”,受于 Dapper 和 OpenZipkin 启发的开源发布的分布式跟踪系统。所谓 OpenTracing 规范,即:一套与平台无关、厂商无关的 Trace 协议,使得开发人员能够方便的添加或更换分布式追踪系统的实现。
作为 CNCF 的一个分布式链路追踪软件明星项目,Jaeger 在架构的设计上沿用了 Zipkin 的架构风格,两者具备很多类似的特性,除了开发语言不同而已。作为后起之秀,基于 Go 的强大特性,使得 Jaeger 在基于云原生生态领域中能够如鱼得水,具备强大的号召力,甚至在一些新技术框架领域中,作为默认首选的分布式链路追踪系统,落地于各种不同的业务场景。虽然已在 2012 年启动研发,但相对于 2017 年启动的 Jaeger 而言,Zipkin 与 Jaeger 在社区中发展势态几乎没多大差异,从侧面说明,Jaeger 已成为新一代的云原生链路追踪系统的布道者。其支持跨平台、多样性的组件追踪,例如:分布式边缘路由组件 Traefik、下一代微服务体系 Istio 等等。
如下列表简要对比了下当前在各大企业中,所采用链路追踪系统的特性对比情况,具体:
能力项 | SkyWalking |
Zipkin | Jaeger |
开发团队 | 华为 |
Spring社区维护 | Uber 工程团队 |
是否开源 | 是 | 是 | 是 |
OpenTracing | 是 | 是 | 是 |
语言支持 | Java、NET Core、NodeJS 、PHP | Go,Java,Ruby,C++,Python(Progress) | Python,Go,Node,Java,C++,C#,PHP,Ruby |
存储 | ES、H2、Mysql、TIDB、Sharding sphere | 内存、 Cassandra、Elasticsearch |
内存、 Cassandra、Elasticsearch |
Span 传输 | gRPC |
HTTP,KAFKA | UTP,HTTP |
易用性 | 简单易接入 | 少数语言支持差,如Python | 接入简单,各种语言SDK丰富 |
基于官网所述,基于 Golang 语言开发,Jaeger 具备如下特性:
- 分布式上下文传递
- 分布式事务监控
- Root Cause 分析
- 服务依赖分析
- 性能、延迟优化
接下来,我们来了解下 Jaeger 的基本架构,首先来看下如下架构示意图,具体可参考如下:
基于上述示意图,我们简要解析下 Jaeger 各个组件以及组件间的关系:
1、客户端库(Client libraries)
Jaeger 客户端是 OpenTracing API 的特定于语言的实现。它们可用于手动或与已经与 OpenTracing 集成的各种现有开源框架(例如 Flask,Dropwizard,gRPC 等)一起为分布式跟踪应用程序进行检测。
检测服务在接收新请求时创建 Span,并将上下文信息(Trace id,Span id 和 Baggage)附加到传出请求。只有 id 和 baggage 随请求一起传播;所有其他概要分析数据(如操作名称,时间,tag 和 log)都不会传播。相反,它在后台异步地传输到 Jaeger 后端。
为了最大程度地减少开销,Jaeger 客户端采用了各种采样策略。对跟踪进行采样时,将捕获分析范围数据并将其传输到 Jaeger 后端。当不对跟踪进行采样时,根本不会收集任何性能分析数据,并且对 OpenTracing API 的调用会被短路,以产生最小的开销。默认情况下,Jaeger 客户端对 0.1% 的 Traces 进行采样(每 1000 条中的 1 条),并且能够从 Jaeger 后端检索采样策略。有关更多信息,请参阅官网相关文档。
2、代理(Agent)
Jaeger 代理 是一个网络守护程序,它侦听通过 UDP 发送的 Span,然后将其分批发送给收集器(Collector)。它旨在作为基础组件部署到所有主机。该代理为客户端抽象了收集器的路由和发现。
3、收集器(Collector)
Jaeger 收集器从 Jaeger 代理接收跟踪,并通过处理管道运行它们。当前,我们的管道会验证跟踪,为其建立索引,执行转换并最终存储它们。
Jaeger 的存储是一个可插拔组件,目前支持 Cassandra,Elasticsearch 和 Kafka。
4、查询(Query)
查询是一项从存储中检索跟踪并托管 UI 来显示跟踪的服务。
5、Ingester
Ingester 是一项从 Kafka Topic 读取并写入另一个存储后端(Cassandra,Elasticsearch)的服务。
以上为基于 Jaeger 概念、特性以及架构的简要解析 ,使得大家能够对 Jaeger 的各个组件有初步的认识。后续将为大家介绍使用 Jaeger 进行分布式追踪的相关实践,至此,本文到此为止,大家有任何问题或建议,可以随时留言、沟通。