乐趣区

关于运维:使用-OpenTelemetry-构建可观测性-05-传播和行李Propagation-Baggage

咱们开发的应用程序可能具备不同的状态和架构:有些是单体利用,有些是微服务。为单体应用程序增加遥测数据相对来说简略,因为所有数据都在同一过程中。然而对于微服务应用程序,状况可能会更具挑战性。

通常,散布式微服务应用程序的不同服务之间仅通过网络连接。然而,当咱们想要创立无效的链路追踪数据,就要思考到上面的问题:

即便是微服务应用程序,咱们也心愿察看到从开始到完结的用户门路,这意味着逾越多个服务的边界。这就是咱们所说的 分布式链路追踪。不过咱们如何实现这一点呢?咱们如何使链路追踪信息贯通可能是散布在多个过程,并且是不同的基础架构上呢?

流传(propagation)

在 OpenTelemetry 中,解决这个挑战的计划是通过 流传 来实现。这意味着以某种形式将链路追踪 ID(和父跨度 ID)传递给被调用服务,以便它们能够将该信息增加到分布式链路追踪门路中的一个跨度上。上面是一个示意图:

这里咱们有三个服务,通过应用流传,咱们可能将跟踪 ID 和父跨度 ID 作为头信息传递。在 Go 中,流传能够通过全局设置来解决:

import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/propagation"
)

// ...

otel.SetTextMapPropagator(
    propagation.NewCompositeTextMapPropagator(propagation.TraceContext{},
        propagation.Baggage{}),
)

在示例代码中,咱们能够在控制器层(Handler,通常用于解决 HTTP 申请并生成相应的响应,承当的作用包含路由和申请散发,申请解决逻辑,响应生成)进行设置:

http.Handle(fmt.Sprintf("/%s/", rootPath),
    otelhttp.NewHandler(http.HandlerFunc(userCart),
        "http_user_cart",
        otelhttp.WithTracerProvider(otel.GetTracerProvider()),
        otelhttp.WithPropagators(otel.GetTextMapPropagator()),
    ))

当从一个服务发送 HTTP 申请到另一个服务时,可通过 otelhttp 库的辅助函数来创立和治理分布式追踪的跨度对象:

import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"

// ...

resp, err := otelhttp.Get(ctx, fmt.Sprintf("%s/%s", userServiceEndpoint, userName))

行李(Baggage)

从上图中能够看出 service 1 生成了一些数据 attr1。这些与 service 1 相干的数据可能要增加到 service 2 或 service 3 所在跨度对象的属性中。因为这些服务可能无奈间接拜访此数据,在 OpenTelemetry 中是通过 行李 来解决这个问题。行李实质上是携带额定信息的键值对,通过申请传递数据给不同服务和组件。

在 Go 中,咱们能够通过以下形式增加行李信息:

    reqAddrBaggage, err := baggage.NewMember("req.addr", r.RemoteAddr)
    if err != nil {// Handle error...}

    reqBaggage, err := baggage.New(reqAddrBaggage)
    if err != nil {// Handle error...}
    ctx = baggage.ContextWithBaggage(ctx, reqBaggage)

这样设置后咱们的 HTTP 申请将包含 req.addr 行李。

后续生产端的服务(在图中,这可能是 service 2 或 service 3),就能够从申请上下文中解析行李:

import "go.opentelemetry.io/otel/baggage"

// ...

reqBaggage := baggage.FromContext(ctx)
span.SetAttributes(attribute.String(
    "req.addr",
    reqBaggage.Member("req.addr").Value()),
)

此代码解析行李信息,并将其作为以后跨度的属性增加进去。

示例

通过之前对流传和行李的探讨,当初让咱们看看 OpenTelemetry 如何发送这些数据。在示例的购物车应用程序中,如果我发出请求并从价格服务或用户服务中查看申请头,将会看到以下两行信息:

Baggage: req.addr=10.244.0.11%3A60086
Traceparent: 00-9861e8c7b097206fed82e0f6b379aae0-4aa019606aed70b6-01

申请头 Traceparent 是链路追踪 ID(本例中是“9861e8c7b097206fed82e0f6b379aae0”)和父跨度 ID(“4aa019606aed70b6”)。还有一个 Baggage,其中包含在申请发动的源服务(购物车服务),它被增加到 req.addr 行李中。下图能够看到 req.addr 行李在用户服务中被援用:

总结

在 OpenTelemetry 中通过应用流传和行李,很好的解决了“分布式链路追踪”中“分布式”的问题。这样能够帮忙您获取更有价值的链路追踪数据!

本文翻译自:https://trstringer.com/otel-part5-propagation/

扩大浏览:

  • 方法论:面向故障解决的可观测性体系建设
  • 白皮书:事件 OnCall 核心建设办法
  • 好工具:FlashDuty – 一站式告警解决平台:告警降噪、排班 OnCall
退出移动版