Press "Enter" to skip to content

分布式追踪最佳实践

分布式跟踪现在已成为现代可观察性堆栈中的基本组成部分。随着向微服务的转变,我们需要一种新的方式来观察我们的服务如何进行交互。分布式跟踪通过允许我们进行请求跟踪(即跟踪分布式系统中各个组件的请求)来提供这种视图。如今,分布式跟踪用于识别性能瓶颈、调试问题以及了解我们的系统在生产环境中如何交互。

然而,实现分布式跟踪是复杂的,团队从中获得的价值在很大程度上取决于其实现方式。实现机制,例如哪些组件被仪器化、采样率和跟踪可视化的质量都会影响公司从跟踪中获得的价值,进而影响开发者的采用情况。此外,这个领域不断发展,不断出现新的工具和技术。

在本文中,让我们看一看2023年分布式跟踪的最佳实践。

什么是分布式跟踪?

分布式跟踪是指一种机制,它允许我们在分布式环境中跟踪单个请求在多个服务之间的传递。

我们为什么需要分布式跟踪。

为了实现这个目标,分布式跟踪工具会将一个唯一的跟踪上下文(跟踪ID)插入到每个请求的头部,并实现机制来确保跟踪上下文在整个请求路径中传播。

请求路径中进行的每个网络调用都会被捕获并表示为一个跨度(span)。跨度是跟踪的基本单位,它表示跟踪中的单个事件,一个跟踪可以有一个或多个跨度。跨度包含了日志消息、与时间相关的数据和其他属性,以提供有关所跟踪操作的信息。

分布式跟踪的结构。

通过其独特的视图,分布式跟踪解锁了一些新的用例/改进现有的用例。它使我们能够了解服务之间的相互依赖关系(例如,谁在调用我的服务)、识别性能瓶颈(哪个特定的数据库调用导致了延迟问题)、快速识别调试的故障点(哪个API导致了这个500错误)以及有更精细的服务级别目标。

分布式跟踪系统的组成部分

要实现任何分布式跟踪系统,我们需要安装四个不同的组件:

  1. 仪器化库
  2. 收集器(预处理器)
  3. 存储后端
  4. 可视化层

如今,对于这些组件,有几种可选方案 – 您可以使用一个单一的平台来完成上述四个组件,或者通过使用不同组件的不同解决方案来组装您的分布式跟踪框架。

跟踪系统的组件。

仪器化库

这是集成到每个应用程序或服务中的部分。当应用程序执行时,仪器化库确保将跟踪ID添加到每个请求中,或者将跟踪上下文(跟踪ID)传播到下一个跨度。该库将这些数据发送到收集器。

收集器

收集器是仪器化库和存储后端之间的中间层。它收集跟踪数据,处理它们(例如聚合跨度、采样)并为存储做准备。

存储后端

存储后端持久化和索引跟踪数据。它通常使用能够处理大量数据的分布式存储系统,并允许高效查询和检索。

可视化层

这是分布式跟踪系统的用户界面。它允许开发人员和运维人员与跟踪数据进行交互。该层提供了基于各种条件进行查询、搜索和过滤跟踪数据的工具。它以视觉上有意义的方式呈现跟踪数据,通常作为跟踪图或时间线,使用户能够分析事件序列并识别瓶颈或问题。

实施分布式跟踪系统很复杂

虽然有几个好处,但实施分布式跟踪系统(尤其是良好的实现)还不是一项容易的“解决”任务。这需要实施团队做出几个决策,并且这些决策对其他工程团队从跟踪中获得的价值产生实质性影响。公司实施分布式跟踪并每年支付50万美元,但普通开发人员一年只使用两次的情况并不少见。请参阅以下一些实施跟踪的最佳实践。

分布式跟踪的最佳实践

选择 OpenTelemetry 进行仪表化

有几个流行的开源追踪框架,如 OpenTelemetry、Jaeger 和 Zipkin。到了 2023 年的今天,OTel(OpenTelemetry)已经成为一个显而易见的选择,原因如下:

  • 广泛覆盖:OTel 提供了适用于不同编程语言和框架的仪表化库和 SDK,并且现在覆盖面广泛。点击这里查看 OTel 的支持情况。
  • 供应商中立:目前,大多数供应商都支持 OTel 的仪表化。因此,您可以使用 OTel 进行仪表化,并将数据推送到任何您选择的供应商。您将获得供应商互操作性和长期可移植性(如果您选择更换供应商)。这是一份原生支持 OTel 数据的可观察性供应商列表,这里有一个连接 OTel 与其他供应商连接的库和插件的注册表。
  • 成熟稳定:OTel 已经发展了几年,得到了广泛的社区支持。在 CNCF 生态系统中,它现在是第二大项目,仅次于 Kubernetes 本身。强大的社区确保它持续快速地发展和支持新技术。

尽可能利用自动仪表化

OpenTelemetry 提供了两种方式来对应用程序和组件进行仪表化 – 手动仪表化和自动仪表化。如果您正在使用 Kubernetes,并且大多数服务是基于 Java、NodeJS 或 Python 的,应大量使用自动仪表化,因为它可以减少实现的工作量。

手动仪表化

开发人员需要将 OTel 代码添加到应用程序中,因此这需要进行代码更改。手动仪表化可以在跨度和追踪方面进行更多的定制。大多数语言都支持手动仪表化 – C++、.NET、Go、Java、Python 等。请参考这里获取最新的列表。

自动仪表化

这是一种在不进行代码更改或重新编译应用程序的情况下对应用程序/服务进行仪表化的方式。一个智能代理会附加到应用程序上,读取其活动并提取跟踪数据。如果您使用 Kubernetes,就可以实现这种方式。目前,OTel 支持 Java、NodeJS、Python 等语言的自动仪表化(点击这里获取最新的列表)。与手动仪表化相比,自动仪表化的跨度和追踪的定制性有限,但对于大多数用例来说已经足够。

从关键路径开始,并逐步扩展

在大型分布式系统中一次性为每个服务/组件进行仪表化是不实际的,因此重要的是要仔细选择首先仪表化哪些路径以及如何从那里扩展。以下是一些指导原则:

从外到内/从用户附近开始

通常最好从外部开始,然后向内部移动。这意味着从请求进入应用程序的点开始,即来自用户或外部客户端的传入请求。从入口点开始,更容易全面了解请求如何在系统中流动。

选择系统中最关键的路径并首先对其进行仪表化

一般的指导原则是确定系统中最重要的请求路径;这些路径可能是最常访问的路径,或对整体应用程序性能监控有最重要影响的路径。首先对这些关键路径进行仪表化,以便向整个组织展示价值,然后从这些路径开始扩展。

始终对请求路径进行端到端的仪表化,以避免跟踪中断

无论您选择哪些路径,都要确保路径进行了端到端的仪表化 – 这意味着请求路径中的每个服务和组件都进行了仪表化,以传播上下文(TraceID)并根据需要生成跨度。任何间断都会导致不完整或中断的跟踪,这将抵消在上游服务中进行仪表化所投入的努力。

有意识地进行采样

在99%的情况下,公司希望对跟踪进行采样。这是因为如果您存储每个跟踪,您可能需要存储和管理大量的数据。

让我们举个例子。假设每个跨度占用500字节(包括标记和日志记录)。如果您的应用程序每秒提供2000个请求,并且有20个不同的服务,那么每秒就会生成20MB的数据,每小时为72GB,每天为1TB,对于一个简单的20个服务的设置来说。

这就是为什么大多数公司最终会存储分布式跟踪的示例。选择正确的采样策略很重要,这样您就可以在关心的事物上保持可见性,同时控制成本。

广义上,有两种采样方法:

1. 提前/基于头部的采样

这是在给定请求生成任何跟踪之前决定要保留哪些跨度的简单方法。这被称为基于头部的采样,因为决策是在请求的开始或“头部”进行的。有时,当决策是在不查看请求的情况下进行时,它被称为无偏采样。在基于头部的采样中,通常使用以下几种机制,如下所示。

  • 概率性或固定比例采样:根据固定采样率(例如1%)随机选择要保留的一部分跟踪
  • 速率限制采样:设置单位时间内要跟踪的请求数量的固定限制。例如,如果速率限制设置为每分钟100个请求,则只会跟踪该分钟内的前100个请求。
  • 基于优先级的采样:基于优先级(例如,关键交易)给请求分配不同的优先级,并相应地调整采样率。优先级较高的请求具有较高的采样率,优先级较低的请求具有较低的采样率。

2. 基于尾部的采样

尾部采样是根据跟踪中的响应(例如高延迟和错误)来决定是否采样的方法。这种方法确保对“有趣”的请求进行跟踪,即使整体采样率很低。然而,与其他更简单的方法相比,尾部采样更难实现,因为您必须将所有跟踪存储在缓冲区中,直到响应返回。本指南详细介绍了尾部采样。

大多数组织通常采用简单的基于头部的概率性采样机制,并采用1-3%的采样率。请参阅此处了解如何在OTel中配置固定比例采样。

选择性地实施自定义跟踪

分布式跟踪的强大之处在于它允许我们报告自定义跟踪跨度。自定义跨度允许我们使用附加的领域特定信息来丰富分布式跟踪,使跟踪数据更有意义。

我们可以将错误状态作为跨度的一部分捕获和记录,或创建进一步描述服务功能的子跨度。有效标记的跨度可以显著减少代码中所需的日志记录语句数量。

在跟踪的上下文中,广度指的是被仪表化的服务或组件的数量,而深度指的是每个跨度中捕获的详细级别。在实施有效的跟踪机制并控制成本的同时,平衡广度和深度非常重要。

通常情况下,尽可能广泛地进行,并在深入了解的地方进行选择。

将跟踪与监视和日志系统集成

确保将跟踪与现有的监视和日志系统连接起来,以便开发人员在故障排除时可以更轻松地相关联这三个数据集。通常,可以通过以下方式实现:

  • 日志注入:使用日志框架或库将跟踪ID/跨度ID直接注入日志中。这样,每条日志消息都有一个可以用于轻松查询特定日志的跟踪ID。
  • 指标标记:在记录指标时,可以包含与跟踪相关的标签或标签。这些标签可以是跟踪ID、跨度名称或其他跟踪特定的元数据。这使得开发人员可以过滤和聚合围绕跟踪数据的指标,并更容易理解分布式系统。

像OpenTelemetry这样的协议已经使您可以轻松实现此功能。

选择现代化的跟踪可视化前端

在前端方面,不同的解决方案之间存在着显著的差异。在收集跟踪数据之后,您需要能够对其进行可视化。良好的跟踪可视化将使您能够看到跟踪请求在系统中的流动,并识别性能瓶颈。

然而,并非所有的跟踪解决方案都提供直观和用户友好的方式来直接可视化和分析这些数据。有些工具在收集和存储跟踪数据方面表现出色(例如Jaeger,Zipkin,AWS XRay),而其他工具更专注于从跟踪数据中提供见解,因此在更复杂的可视化和分析方面投入更多(例如Honeycomb,Lighstep,Helios)。

好的可视化工具应该提供开箱即用的仪表板,自动为您提供服务依赖图,具有甘特图和瀑布追踪可视化,并允许对追踪进行详细查询和过滤。这篇文章对分布式追踪中的可视化提供了一个全面的观点。

探索结合人工智能和追踪的下一代工具

随着OTel的快速成熟,仪器化已经变得相当标准化。同样,在过去几年中,存储和查询在可观察性行业也已广泛成为商品化。今天,在可视化和分析层面上有一些差异化,尽管即使如此也没有什么意义。

出现了一类解决方案,利用分布式追踪数据上的人工智能来生成关于问题原因的推理。这些解决方案还具有最现代化的追踪堆栈,并且使实施和管理变得极其简单。例如,像ZeroK这样的解决方案可以让您执行以下操作:

  • 一次性在所有组件上安装分布式追踪,无需任何代码更改;所有服务、数据库和队列都会立即被覆盖,使用OTel和eBPF。
  • 它们消除了采样的需求-它们处理100%的追踪,并使用人工智能自动识别异常/“有趣”的追踪以进行存储(例如,错误追踪,高延迟追踪)。
  • 将异常追踪与其他上下文信息(例如,日志)一起附加,以在需要时帮助调试。
  • 对这些追踪应用LLMs,自动识别您生产问题的可能原因。

投资于开发者入职培训

这是一个经常被忽视但至关重要的因素,它将推动您组织中分布式追踪的成功。请记住,分布式追踪是复杂的,对于新的开发人员来说很难有效地使用它。公司通常只有少数几个强大的用户使用追踪平台,而且通常是每个季度几次。

开发人员需要学习如何解释追踪数据,理解不同微服务之间的关系,并使用分布式追踪工具来解决问题。他们必须得到有关一致的命名约定、适当的仪器化和理解追踪上下文传播的最佳实践的指导。为分布式追踪计划开发者入职培训是一项战略投资。它不仅加速了追踪在系统中的集成,还培养了一种文化,开发人员是系统可见性、可靠性和性能持续改进的积极参与者。

结论

我们讨论了分布式追踪的最佳实践以及您可以采取的措施使这一过程更加容易。分布式追踪不再是一种新奇,它已经演变成可观察性堆栈中的至关重要的一部分。

Leave a Reply

Your email address will not be published. Required fields are marked *