上下文传播
通过上下文传播,信号(追踪、指标和日志)可以相互关联,无论它们在哪里生成。虽然不限于追踪,但上下文传播允许追踪跨越任意分布在进程和网络边界上的服务构建系统的因果信息。
要理解上下文传播,你需要理解两个独立的概念:上下文和传播。
上下文
上下文是一个对象,其中包含发送和接收服务,或执行单元,用于关联一个信号与另一个信号的信息。
当服务 A 调用服务 B 时,服务 A 会在上下文中包含一个跟踪 ID 和一个跨度 ID。服务 B 使用这些值来创建一个属于同一跟踪的新跨度,并将其设置为来自服务 A 的跨度的父级。这使得能够跨服务边界跟踪请求的完整流程。
传播
传播是将上下文在服务和进程之间移动的机制。它序列化或反序列化上下文对象,并提供需要从一个服务传播到另一个服务的信息。
传播通常由仪器库处理,并且对用户是透明的。如果你需要手动传播上下文,可以使用传播器 API。
OpenTelemetry 维护着几个官方的传播器。默认的传播器使用 W3C TraceContext 规范指定的标头。
示例
一个名为Frontend的服务,提供诸如POST /cart/add和GET /checkout/等不同的 HTTP 端点,通过 HTTP 端点GET /product调用下游服务Product Catalog,以获取用户想要添加到购物车或作为结账一部分的产品的详细信息。为了在Frontend发来的请求的上下文中理解Product Catalog服务中的活动,上下文(此处:跟踪 ID 和跨度 ID 作为“父 ID”)使用traceparent标头进行传播,正如 W3C TraceContext 规范中所定义的那样。这意味着 ID 被嵌入到标头的字段中
<version>-<trace-id>-<parent-id>-<trace-flags>
例如
00-a0892f3577b34da6a3ce929d0e0e4736-f03067aa0ba902b7-01
追踪
如前所述,上下文传播允许追踪跨服务构建因果信息。在这个例子中,通过从traceparent标头中提取远程上下文并将其注入本地上下文以设置跟踪 ID 和父 ID,可以关联对服务Product Catalog的 HTTP 端点GET /product的两次调用及其在服务Frontend中的上游调用。通过这种方式,在 后端(如 Jaeger)中可以看到两个请求作为同一个跟踪的跨度。
日志
OpenTelemetry SDK 能够自动将日志与追踪相关联。这意味着它们可以将上下文(跟踪 ID、跨度 ID)注入到日志记录中。这不仅使您能够在日志所属的跟踪和跨度的上下文中查看日志,而且还使您能够跨服务或执行单元边界查看属于同一组的日志。
指标
对于指标,上下文传播使您能够在该上下文中聚合测量。例如,您不仅可以查看所有GET /product请求的响应时间,还可以获得组合指标,如POST /cart/add > GET /product和GET /checkout < GET /product。
| 名称 | 每秒调用数 | 平均响应时间 |
|---|---|---|
* > GET /product | 370 | 300ms |
POST /card/add > GET /product | 330 | 130ms |
GET /checkout > GET /product | 40 | 1703ms |
自定义上下文传播
对于大多数用例,您会发现仪器库或原生库仪器会为您处理上下文传播。在某些情况下,没有这样的支持,您想自己创建这种支持。为此,您需要利用前面提到的传播器 API。
- 在发送方,上下文被注入到载体中,例如,注入到 HTTP 请求的标头中。在其他情况下,您需要找到一个可以存储请求元数据的地方。
- 在接收方,上下文从载体中提取。同样,在 HTTP 的情况下,这是从标头中检索的。在其他情况下,您选择在发送方选择用来存储上下文的地方。
请注意,可以在没有专用元数据字段的协议中传播上下文,但您必须确保在接收方,在数据被处理之前将它们提取并删除,否则可能会产生未定义的行为。
以下语言提供了自定义上下文传播的分步教程
安全最佳实践
传播涉及跨服务边界发送和接收数据,这可能会带来安全隐患。
外部服务
当您的服务与外部服务(您不拥有或不信任的服务)交互时,请考虑以下几点:
- 入站上下文:在接受来自外部源的上下文时要小心。恶意行为者可能会发送伪造的跟踪标头来操纵您的跟踪数据或利用上下文解析中的漏洞。您可能需要忽略或清理来自不受信任源的入站上下文。
- 出站上下文:在传播到外部服务的内容时要小心。内部跟踪 ID、跨度 ID 或 Baggage 项可能会泄露有关您内部架构或业务逻辑的敏感信息。您可能希望配置您的传播器,使其不向外部或面向公众的端点发送上下文。
Baggage
Baggage 允许您传播任意键值对。由于这些数据会跨服务边界传播,请避免在 Baggage 中放入敏感信息(如用户凭证、API 密钥或 PII),因为它们可能会被记录或发送到不受信任的下游服务。
语言 SDK 中的支持
对于 OpenTelemetry API 和 SDK 的各个特定语言实现,您将在各自的文档页面中找到有关上下文传播支持的详细信息。
对于 .NET、Rust 和 Swift 语言,缺少特定语言的上下文传播文档。如果您了解其中任何一种语言并有兴趣提供帮助,请了解如何贡献!
规范
要了解更多关于上下文传播的信息,请参阅上下文规范。