OpenTelemetry 之 Tracing

OpenTelemetry 之 Tracing_第1张图片

OpenTelemetry 的使命:“通过普遍的、高质量和便携式遥测数据,以实现有效的可观测性。”

01

广为人知
的 OpenTelemetry

OpenTelemetry 这个话题我们已经不再陌生,不仅讨论过多次,也在生产开发中实践。对于它的探索从未停止,今天就来着重探讨一下 OpenTelemetry 的 tracing 部分,也是 OTEL 三大支柱中最成熟的部分。

在此之前,我们先回顾一下:什么是 OpenTelemetry?

软件开发人员为了快速定位生产中的问题,通常需要收集大量数据。但近年来,随着服务数量呈爆炸式增长,传统的收集数据并排除系统故障的方法变得越来越复杂。而 OpenTelemetry 作为新一代可观测性标准框架,能够在单一规范下遥测数据,正逐渐在分布式系统中成为检测、排除故障和解决性能问题的主要工具。它由 CNCF 社区共同开发,提供了一组不限语言无关、不限供应商无关的标准 API 和 SDK ,用来收集服务运行时产生的日志、指标和链路数据。OpenTelemetry 兼容 OpenCensus 和 OpenTracing ,拥有检测云原生应用程序的能力,这有助于我们了解软件的性能和行为方式。

02

什么是
Trace (链路追踪)?

Distributed Tracing(分布式链路追踪),通常被称作 trace 。Trace 为软件开发者提供了单个 api 请求的跨服务的全局调用视图,当客户端向服务端发起一个请求时,通过链路追踪,开发人员可以知道,这个请求在不同的服务和系统组件之间,究竟发生了什么,这一点在微服务架构中尤其重要,因为在微服务架构中,任意一个微服务的故障,都可能会导致应用整体不可用。 没有 trace 之前,开发人员很难定位分布式系统中的性能和故障问题。

OpenTelemetry 之 Tracing_第2张图片

Trace 和 Span 图源:https://opentelemetry.io/docs/

链路追踪中最重要的概念当属 trace 与 span(跨度)。上图是一个 trace 示意图,一个 trace 是多个相互关联、之间具有父子关系的 span 集合。每个 trace 中只会有一个 span 没有父 span ,它叫做 parent span 或 root span ,即上图中顶部的 span , root span 的时间跨度代表着整个链路的操作耗时。

上面对 trace 与 span 概念解释可能有些抽象,结合一个具体的业务场景来讲,假设现在有一个提供拼车服务的小程序,当用户发起拼车订单时,从客户端发起的一个 http 请求链路可能如下图所示:

OpenTelemetry 之 Tracing_第3张图片

图源:https://opentelemetry.io/docs/

1. 首先,客户端发起 http 请求。

2. auth 服务对用户的请求进行鉴权。

3. payment 服务验证用户预留的付款信息,并完成了一次数据库操作。

4. dispatch 服务为用户调度附近的司机。

可以看到,服务中的每个操作都会产生一个与之对应的 span ,每个 span 内部都封装了一个系统内部的调用事件描述以及开始与结束时间,它就是链路追踪中的的 ”调用栈“,正是由这些具备父子关系的 span 最终构成了完整的 trace 链路。

03

OpenTelemetry
与链路追踪

Trace 的概念其实由来已久,其起源可以追溯到 X-Trace 、Dapper ,尤其是 Dapper ,它对链路追踪有着深远的影响。OpenTelemetry 使用的许多模型和设计都参考了此项目。OpenTelemetry 为 trace 定义了一套新的数据模型,并且规范了数据的采集、处理、导出方式。并为不同的语言提供了标准的 SDK ,并且这套规范与语言无关,供应商无关。

以 Jaeger 为例展示链路追踪

Trace 数据一旦被收集,就可以通过一些第三方的可视化软件展示出来,允许我们直观的理解全链路调用关系。这里我们通过开源的 jaeger 来窥探链路追踪的全貌。

OpenTelemetry 之 Tracing_第4张图片

图源:https://www.jaegertracing.io/

上图是 jaeger 的链路追踪 UI 界面,这张图中设计到的业务逻辑如下:

1. 第一个请求是由 orders-service 发出的,我们可以看到它是分层结构中列出的第一个 Span ,即 “父” Span ;

2. 接着,orders-service 调用了 user-service 的 users/verify 接口;

3. 最后,orders-service 调用了 stock-service 的 update-stock 接口, stock-service 调用了 Mongo DB 完成了一次数据库操作。

由此而完成一次链路追踪。

另外,通过可视化的时间线,我们能够看出每个请求的长度、开始和结束的时间以及事件发生的顺序。由于每个操作都可以生成自己的日志和指标,我们因此也能识别出不同的分布式系统中性能问题。

04

OpenTelemetry
基础架构

简单来讲,OpenTelemetry 基础架构分为三层:

OpenTelemetry 之 Tracing_第5张图片

1. 应用层:一旦应用程序通过 otel 的 sdk 完成了数据接入,日志、指标、链路数据就会源源不断地被发送至 OpenTelemetry collector 。

2. OpenTelemetry collector :数据收集后,进行转换、转发遥测数据,有选择性地将数据发送到数据库。

3. 可视化层:利用一些支持 OpenTelmetry 的第三方软件对数据进行可视化展示(比如我们前面提到的 Jaeger )。

05

OpenTelemetry
SDK 如何工作?

所以现在我们已经知道了OpenTelemetry 是什么以及其技术栈组成,是时候再深入看看 OpenTelemetry SDK 是如何工作的。

假设应用程序有两个服务:服务A 和服务 B。服务 A 向服务 B 发送 API 调用,一旦发生这种情况,服务 B 就会被写入数据库。这两种服务都使用的是OpenTelemetry collector ,也都有 OpenTelemetry SDK 。

OpenTelemetry 之 Tracing_第6张图片

如上图,一旦服务A 对服务 B 进行了 API 调用,服务 A 还会向 collector 发送一个对服务 B 描述调用的 span ,实际上是让 collector 知道它发送了一个 API 调用(使其成为链路追踪中的父级)。现在,服务 A 和服务 B 之间存在 “父/子” 关系(服务 A 是后续所有操作的父项)。

可以看出,OpenTelemetry 在对服务 B 的 API 调用中,注入了有关父级 span 的详细信息。它使用 HTTP headers 追踪上下文( trace ID 、span ID 等)并注入到自定义的 header 中。服务 B 收到 HTTP 调用后将提取相同的 header ,紧接着,服务 B 的后续操作都将报告给其子项。

这一步骤引起 OpenTelemetry 的另一个关键面:Trace 的全局上下文传播。这是一种能够跨服务关联 span 的途径,通过网络传输 HTTP header 等元数据。我们知道数据一般分为 header 和 body ,比如 http 的 header 和 body,由于 body 一般放着业务数据,所以不宜在 body 中传递 context,应该在 header 中传递 context 。在这里,每个 header 会包含一个 trace ID(该 ID 表示已发生调用的 HTTP ),并且还包括一个 span ID(表示刚刚发生的事件)。

由于服务 B 也实现了 SDK,因此它还会将数据发送到 collector ,通知 collector 已收到来自服务 A(其父级)的 API 调用。服务 B 对数据库的调用也是如此,虽然创建另一个 span ,但 trace ID 与服务 A 创建的初始 trace ID 相同。

06

OpenTelemetry
自动和手动检查

检测:是指从不同的库收集数据中产生代表它们行为 span 的过程。这里有两种方式可以创建 span,分别为:

自动检测:不需要写任何代码去收集 span。

手动检测:需要在你的应用程序中写一些代码去收集 span。

自动检测

这里有 OpenTelemetry 社区已经开发好的库可以实现,它们会自动从我们的应用程序库里创建 span (例如:Redis client , HTTP client )。

一旦我们使用 HTTP 库来发送 HTTP 请求,检测过程就会自动创建一个新的 span 。

手动检测

手动检测的工作原理是手动向应用程序中添加代码,以便定义每个 span 开始和结束的行为。

提示:使用自动检测, OpenTelemetricy 提供了一个官方的地址可以查找所有可用的检测库:https://opentelemetry.io/registry/

几种使用手动检测的通用用例:

不支持自动检测:并非所有的库都能够自动检测,所以在不支持自动检测的情况下,我们必须自己编写代码进行手动检测。

内部的代码库:有些社区和组织开发了自己的代码库,这也需要我们创建手动检测。如果是这种情况,可以参考以下原则:

1. 从一些同样具有检测的开源库里汲取灵感。

2. 遵循 OpenTelemetric 社区的规范,以便第三方的工具能够正常工作。

07

总结

类似于 Kubernetes 已经成为容器编排的标准,企业不再需要构建自己的编排平台。OpenTelemetry 为云原生应用程序的可观测性也提供了真实可行的标准,虽然它本身并不提供解决方案,但统一的标准让我们可以把更多精力放在交付新功能,做出更完善的可观测性产品上面。高质量的遥测数据为实现强大的可观测性提供了保障,Tracing 是观测性中非常重要的一个环节,当然, log 和 metric 也不可或缺。

参考链接:

[1] jaegertracing.io: https://www.jaegertracing.io/

[2] OpenTelemetry.io: https://opentelemetry.io/docs/


 本文作者 

OpenTelemetry 之 Tracing_第7张图片

程锐

云原生研究院产品经理

你可能感兴趣的:(云原生,java,开发语言)