追踪

概述

分布式追踪允许开发人员获取大型面向服务的架构中调用流的可视化视图。它在了解序列化、并行性和延迟来源方面非常宝贵。Envoy 支持与系统范围追踪相关的三个功能

  • 请求 ID 生成:Envoy 会在需要时生成 UUID 并填充 x-request-id HTTP 标头。应用程序可以转发 x-request-id 标头以进行统一日志记录以及追踪。可以使用扩展在每个 HTTP 连接管理器 的基础上配置此行为。

  • 客户端追踪 ID 加入x-client-trace-id 标头可用于将不受信任的请求 ID 加入到可信的内部 x-request-id

  • 外部追踪服务集成:Envoy 支持可插拔的外部追踪可视化提供者,它们被分为两个子组

如何发起追踪

处理请求的 HTTP 连接管理器必须具有 tracing 对象设置。追踪可以以多种方式发起

追踪上下文传播

Envoy 提供了报告有关网格中服务之间通信的追踪信息的功能。但是,为了能够将调用流中各种代理生成的追踪信息片段关联起来,服务必须在入站和出站请求之间传播某些追踪上下文。

无论使用哪种追踪提供者,服务都应传播 x-request-id 以便能够关联已调用服务的跨越日志记录。

注意

Envoy 的请求 ID 实现是可扩展的,默认为 UuidRequestIdConfig 实现。此扩展的配置可以在 HTTP 连接管理器 字段中提供(有关示例,请参阅该字段的文档)。默认实现将修改请求 ID UUID4 以将最终追踪原因打包到 UUID 中。此功能允许跨 Envoy 集群进行稳定的采样,如 x-request-id 标头文档中所述。但是,追踪原因打包可能会破坏必须维护的外部生成的请求 ID。可以使用 pack_trace_reason 字段禁用此行为,代价是也禁用部署中的稳定追踪原因传播和相关功能。

注意

默认情况下,Envoy 的采样策略由 x-request-id 的值决定。但是,此类采样策略仅对 Envoy 集群有效。如果集群中存在不是 Envoy 的服务代理,则会在不考虑该代理的策略的情况下执行采样。对于包含多个服务代理(例如这种代理)的网格,绕过 Envoy 的采样策略并根据追踪提供者的采样策略进行采样更有效。这可以通过将 use_request_id_for_trace_sampling 设置为 false 来实现。

追踪提供者还需要额外的上下文,以使父/子关系(跨度(工作逻辑单元))之间能够被理解。这可以通过直接在服务本身内使用 LightStep(通过 OpenTelemetry API)或 Zipkin 追踪器来实现,以便从入站请求中提取追踪上下文并将其注入到任何后续的出站请求中。这种方法还将使服务能够创建额外的跨度,描述在服务内部完成的工作,这在检查端到端追踪时可能会有用。

或者,追踪上下文也可以由服务手动传播

每个追踪包含哪些数据

端到端追踪由一个或多个跨度组成。跨度表示具有开始时间和持续时间的逻辑工作单元,并且可以包含与其关联的元数据。Envoy 生成的每个跨度都包含以下数据

  • 通过 --service-cluster 设置的起源服务集群。

  • 请求的开始时间和持续时间。

  • 通过 --service-node 设置的起源主机。

  • 通过 x-envoy-downstream-service-cluster 标头设置的下游集群。

  • HTTP 请求 URL、方法、协议和用户代理。

  • 通过 custom_tags 设置的额外自定义标签。

  • 上游集群名称、可观察性名称和地址。

  • HTTP 响应状态代码。

  • GRPC 响应状态和消息(如果可用)。

  • 当 HTTP 状态为 5xx 或 GRPC 状态不为“OK”时,表示服务器端错误的错误标签。有关 GRPC 状态代码的更多信息,请参阅 GRPC 的文档

  • 追踪系统特定元数据。

跨度还包含名称(或操作),默认情况下定义为已调用服务的地址。但是,这可以使用路由上的 config.route.v3.Decorator 进行自定义。名称也可以使用 x-envoy-decorator-operation 标头进行覆盖。

Envoy 会自动将跨度发送到跟踪收集器。根据跟踪收集器,多个跨度会使用通用信息(例如全局唯一请求 ID x-request-id (LightStep)或跟踪 ID 配置(Zipkin 和 Datadog))拼接在一起。有关如何在 Envoy 中设置跟踪的更多信息,请参阅 v3 API 参考

行李

行李提供了一种机制,使数据在整个跟踪过程中始终可用。虽然元数据(如标签)通常是通过带外方式传递给收集器的,但行李数据被注入到实际的请求上下文中,并在请求持续期间可供应用程序使用。这使得元数据能够从请求的开始透明地传递到整个网格中,而无需依赖于应用程序特定的修改来进行传播。有关行李的更多信息,请参阅 OpenTelemetry 文档

跟踪提供程序对获取和设置行李的支持程度各不相同。

  • LightStep(以及任何符合 OpenTelemetry 的跟踪器)可以读写行李。

  • Zipkin 支持尚未实现。

  • X-Ray 和 OpenCensus 不支持行李。

不同类型的跨度

如上一段所述,跟踪由一个或多个跨度组成,这些跨度可能具有不同的类型。SkyWalking、ZipKin 和 OpenTelemetry 等跟踪系统提供相同或相似的跨度类型。最常见的类型是 CLIENT 和 SERVER。CLIENT 类型的跨度由客户端为发送到服务器的请求生成,而 SERVER 类型的跨度由服务器为从客户端接收到的请求生成。

一个基本的跟踪链看起来像下面的代码片段。通常,服务器跨度的父跨度应该是客户端跨度。链中的每一跳都必须确保跨度类型的正确性。

-> [SERVER -> CLIENT] -> [SERVER -> CLIENT] -> ...
          App A                 App B

Envoy 的不同模式

由于 Envoy 广泛应用于服务网格作为 sidecar,因此了解 Envoy 的不同跟踪模式非常重要。

在第一种模式下,Envoy 用作 sidecar。sidecar 及其关联的应用程序被视为跟踪链中的一跳。如果使用具有类型跨度的跟踪系统,理想的跟踪链可能看起来像下面的代码片段。

-> [[SERVER (inbound sidecar) -> App -> CLIENT (outbound sidecar)]] -> ...
                                 App

如您所见,在第一种模式下,入站 sidecar 将始终生成 SERVER 跨度,而出站 sidecar 将始终生成 CLIENT 跨度。应用程序不会生成任何跨度,但只会传播跟踪上下文。

在第二种模式下,Envoy 用作网关。或者,Envoy 可以用作 sidecar,但这种情况下,sidecar 及其应用程序被视为跟踪链中的独立跳。如果使用具有类型跨度的跟踪系统,理想的跟踪链可能看起来像下面的代码片段。

-> [SERVER -> CLIENT] -> [SERVER -> CLIENT] -> [SERVER -> CLIENT] -> [SERVER -> CLIENT] -> ...
        Gateway           Inbound Sidecar            App             Outbound Sidecar

如您所见,在第二种模式下,Envoy 将为下游请求生成 SERVER 跨度,为上游请求生成 CLIENT 跨度。应用程序也可以为其自身的工作生成跨度。

要启用此模式,请将 spawn_upstream_span 明确设置为 true。这会告诉跟踪提供程序为上游请求生成 CLIENT 跨度,并将 Envoy 视为跟踪链中的独立跳。