开放分布式追踪(OpenTracing)入门与 Jaeger 实现

摘要: 分布式系统的运维挑战 容器、Serverless 编程方式的诞生极大提高了软件交付与部署的效率。在架构的演化过程当中,能够看到两个变化: 应用架构开始从单体系统逐步转变为微服务,其中的业务逻辑随之而来就会变成微服务之间的调用与请求。

点此查看原文: click.aliyun.com/m/43347/

分布式系统的运维挑战

容器、Serverless 编程方式的诞生极大提高了软件交付与部署的效率。在架构的演化过程当中,能够看到两个变化:
  • 应用架构开始从单体系统逐步转变为微服务,其中的业务逻辑随之而来就会变成微服务之间的调用与请求。
  • 资源角度来看,传统服务器这个物理单位也逐渐淡化,变成了看不见摸不到的虚拟资源模式。
从以上两个变化能够看到这种弹性、标准化的架构背后,原先运维与诊断的需求也变得愈来愈复杂。为了应对这种变化趋势,诞生一系列面向 DevOps 的诊断与分析系统,包括集中式日志系统(Logging),集中式度量系统(Metrics)和分布式追踪系统(Tracing)。

Logging,Metrics 和 Tracing

Logging,Metrics 和 Tracing 有各自专一的部分。
  • Logging - 用于记录离散的事件。例如,应用程序的调试信息或错误信息。它是咱们诊断问题的依据。
  • Metrics - 用于记录可聚合的数据。例如,队列的当前深度可被定义为一个度量值,在元素入队或出队时被更新;HTTP 请求个数可被定义为一个计数器,新请求到来时进行累加。
  • Tracing - 用于记录请求范围内的信息。例如,一次远程方法调用的执行过程和耗时。它是咱们排查系统性能问题的利器。

这三者也有相互重叠的部分,以下图所示。

经过上述信息,咱们能够对已有系统进行分类。例如,Zipkin 专一于 tracing 领域;Prometheus 开始专一于 metrics,随着时间推移可能会集成更多的 tracing 功能,但不太可能深刻 logging 领域; ELK,阿里云日志服务这样的系统开始专一于 logging 领域,但同时也不断地集成其余领域的特性到系统中来,正向上图中的圆心靠近。

关于三者关系的更详细信息可参考 Metrics, tracing, and logging。下面咱们重点介绍下 tracing。

Tracing 的诞生

Tracing 是在90年代就已出现的技术。但真正让该领域流行起来的仍是源于 Google 的一篇论文" Dapper, a Large-Scale Distributed Systems Tracing Infrastructure",而另外一篇论文" Uncertainty in Aggregate Estimates from Sampled Distributed Traces"中则包含关于采样的更详细分析。论文发表后一批优秀的 Tracing 软件孕育而生,比较流行的有:
  • Dapper(Google) : 各 tracer 的基础
  • StackDriver Trace (Google)
  • Zipkin(twitter)
  • Appdash(golang)
  • 鹰眼(taobao)
  • 谛听(盘古,阿里云云产品使用的Trace系统)
  • 云图(蚂蚁Trace系统)
  • sTrace(神马)
  • X-ray(aws)
分布式追踪系统发展很快,种类繁多,但核心步骤通常有三个:代码埋点,数据存储、查询展现。

下图是一个分布式调用的例子,客户端发起请求,请求首先到达负载均衡器,接着通过认证服务,计费服务,而后请求资源,最后返回结果。
数据被采集存储后,分布式追踪系统通常会选择使用包含时间轴的时序图来呈现这个 Trace。
但在数据采集过程当中,因为须要侵入用户代码,而且不一样系统的 API 并不兼容,这就致使了若是您但愿切换追踪系统,每每会带来较大改动。

OpenTracing

为了解决不一样的分布式追踪系统 API 不兼容的问题,诞生了 OpenTracing 规范。
OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。
+-------------+ +---------+ +----------+ +------------+ | Application | | Library | | OSS | | RPC/IPC | | Code | | Code | | Services | | Frameworks | +-------------+ +---------+ +----------+ +------------+ | | | | | | | | v v v v +------------------------------------------------------+ | OpenTracing | +------------------------------------------------------+ | | | | | | | | v v v v +-----------+ +-------------+ +-------------+ +-----------+ | Tracing | | Logging | | Metrics | | Tracing | | System A | | Framework B | | Framework C | | System D | +-----------+ +-------------+ +-------------+ +-----------+

OpenTracing 的优点

  • OpenTracing 已进入 CNCF,正在为全球的分布式追踪,提供统一的概念和数据标准。
  • OpenTracing 经过提供平台无关、厂商无关的 API,使得开发人员可以方便的添加(或更换)追踪系统的实现。

OpenTracing 数据模型

OpenTracing 中的 Trace(调用链)经过归属于此调用链的 Span 来隐性的定义。
特别说明,一条 Trace(调用链)能够被认为是一个由多个 Span 组成的有向无环图(DAG图),Span 与 Span 的关系被命名为 References。
例如:下面的示例 Trace 就是由8个 Span 组成:

单个 Trace 中,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)

有些时候,使用下面这种,基于时间轴的时序图能够更好的展示 Trace(调用链):
单个 Trace 中,span 间的时间关系 ––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time [Span A···················································] [Span B··············································] [Span D··········································] [Span C········································] [Span E·······] [Span F··] [Span G··] [Span H··]

每一个 Span 包含如下的状态:(译者注:因为这些状态会反映在 OpenTracing API 中,因此会保留部分英文说明)
  • An operation name,操做名称
  • A start timestamp,起始时间
  • A finish timestamp,结束时间
  • Span Tag,一组键值对构成的 Span 标签集合。键值对中,键必须为 string,值能够是字符串,布尔,或者数字类型。
  • Span Log,一组 span 的日志集合。

每次 log 操做包含一个键值对,以及一个时间戳。
键值对中,键必须为 string,值能够是任意类型。

可是须要注意,不是全部的支持 OpenTracing 的 Tracer,都须要支持全部的值类型。
  • SpanContext,Span 上下文对象 (下面会详细说明)
  • References(Span间关系),相关的零个或者多个 Span(Span 间经过 SpanContext 创建这种关系)

每个 SpanContext 包含如下状态:
  • 任何一个 OpenTracing 的实现,都须要将当前调用链的状态(例如:trace 和 span 的 id),依赖一个独特的 Span 去跨进程边界传输
  • Baggage Items,Trace 的随行数据,是一个键值对集合,它存在于 trace 中,也须要跨进程边界传输

更多关于 OpenTracing 数据模型的知识,请参考 OpenTracing语义标准

OpenTracing 实现

这篇 文档列出了全部 OpenTracing 实现。在这些实现中,比较流行的为 JaegerZipkin

Jaeger

Jaeger 是 Uber 推出的一款开源分布式追踪系统,兼容 OpenTracing API。

Jaeger 架构

如上图所示,Jaeger 主要由如下几部分组成。
  • Jaeger Client - 为不一样语言实现了符合 OpenTracing 标准的 SDK。应用程序经过 API 写入数据,client library 把 trace 信息按照应用程序指定的采样策略传递给 jaeger-agent。
  • Agent - 它是一个监听在 UDP 端口上接收 span 数据的网络守护进程,它会将数据批量发送给 collector。它被设计成一个基础组件,部署到全部的宿主机上。Agent 将 client library 和 collector 解耦,为 client library 屏蔽了路由和发现 collector 的细节。
  • Collector - 接收 jaeger-agent 发送来的数据,而后将数据写入后端存储。Collector 被设计成无状态的组件,所以您能够同时运行任意数量的 jaeger-collector。
  • Data Store - 后端存储被设计成一个可插拔的组件,支持将数据写入 cassandra、elastic search。
  • Query - 接收查询请求,而后从后端存储系统中检索 trace 并经过 UI 进行展现。Query 是无状态的,您能够启动多个实例,把它们部署在 nginx 这样的负载均衡器后面。

Jaeger 存在的问题

  • 须要架设并维护存储。
  • UI比较薄弱,有一些个性化的分析需求没法快速知足(例如对比,统计延迟分布等)。

Jaeger on Aliyun Log Service

Jaeger on Aliyun Log Service 是基于 Jeager 开发的分布式追踪系统,支持将采集到的追踪数据持久化到 日志服务中,并经过 Jaeger 的原生接口进行查询和展现。

优点
  • 原生 Jaeger 仅支持将数据持久化到 cassandra 和 elasticsearch 中,用户须要自行维护后端存储系统的稳定性,调节存储容量。Jaeger on Aliyun Log Service 借助阿里云日志服务的海量数据处理能力,让您享受 Jaeger 在分布式追踪领域给您带来便捷的同时无需过多关注后端存储系统的问题。
  • Jaeger UI 部分仅提供查询、展现 trace 的功能,对分析问题、排查问题支持不足。使用 Jaeger on Aliyun Log Service,您能够借助日志服务强大的查询分析能力,助您更快分析出系统中存在的问题。
  • 相对于 Jaeger 使用 elasticsearch 做为后端存储,使用日志服务的好处是支持按量付费,成本仅为 elasticsearch 的13%。参阅自建ELK vs 日志服务(SLS)全方位对比

配置步骤


使用实例

HotROD 是由多个微服务组成的应用程序,它使用了 OpenTracing API 记录 trace 信息。
下面经过一段视频向您展现如何使用 Jaeger on Aliyun Log Service 诊断 HotROD 出现的问题。视频包含如下内容:
  1. 如何配置日志服务
  2. 如何经过 docker-compose 运行 Jaeger
  3. 如何运行 HotROD
  4. 经过 Jaeger UI 如何检索特定的 trace
  5. 经过 Jaeger UI 如何查看 trace 的详细信息
  6. 经过 Jaeger UI 如何定位应用的性能瓶颈
  7. 经过日志服务管理控制台,如何定位应用的性能瓶颈
  8. 应用程序如何使用 OpenTracing API

参考资料


特别感谢

Jaeger on Aliyun Log Service 是基于阿里云MVP @WPH95 在业余时间工做整理而成,感谢 MVP
的杰出贡献!

识别如下二维码,阅读更多干货