首页 > 其他分享 >使用 OpenTelemetry 构建可观测性 05 - 传播和行李(Propagation & Baggage)

使用 OpenTelemetry 构建可观测性 05 - 传播和行李(Propagation & Baggage)

时间:2023-08-24 09:22:10浏览次数:40  
标签:otel 服务 addr 05 行李 req OpenTelemetry Baggage 链路

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

通常,分布式微服务应用程序的不同服务之间仅通过网络连接。然而,当我们想要创建有效的链路追踪数据,就要考虑到下面的问题:

20230815165150

即使是微服务应用程序,我们也希望观察到从开始到结束的用户路径,这意味着跨越多个服务的边界。这就是我们所说的分布式链路追踪。不过我们如何实现这一点呢?我们如何使链路追踪信息贯穿可能是分布在多个进程,并且是不同的基础架构上呢?

传播( propagation )

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

20230815165043

这里我们有三个服务,通过使用传播,我们能够将跟踪 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 行李在用户服务中被引用:

20230815164830

总结

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

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

扩展阅读:

标签:otel,服务,addr,05,行李,req,OpenTelemetry,Baggage,链路
From: https://www.cnblogs.com/ulricqin/p/17653273.html

相关文章

  • 一个意外错误使你无法创建该文件。如果你继续收到此错误,可以使用错误代码来搜索有关此
     解决方法:正确方法应该是以管理员权限打开cmd,然后执行 icaclsc:\/setintegritylevelM ......
  • 1005:地球人口承载力估计
    1005:地球人口承载力估计时间限制:1000ms      内存限制:65536KB提交数:143681   通过数:82259【题目描述】假设地球上的新生资源按恒定速度增长。照此测算,地球上现有资源加上新生资源可供x亿人生活a年,或供y亿人生活b年。为了能够实现可持续发展,避免资源......
  • VA01/VA02/VA03/VA05 销售订单隐藏价格
    1、业务需求针对用户使用销售订单时,判断是否有权限,没有权限时隐藏销售订单抬头和行项目的价格相关字段2、增强实现2.1、隐藏抬头和行项目价格隐藏抬头和行项目表格中的净值和净价字段在程序MV45AFZZ→USEREXIT_FIELD_MODIFICATION中写隐式增强"--------------------@斌将......
  • Leetcode605——种花问题
    假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n......
  • python必坑知识点05
    1、js基本数据类型undefined,null,number,string,symbol,boolean,object,array,date2、js中的拷贝(深浅拷贝)https://www.cnblogs.com/echolun/p/7889848.htmlhttps://www.bilibili.com/video/BV1iu411e7DS/?spm_id_from=333.337.search-card.all.click&vd_source=69181b959bc0......
  • [代码随想录]Day25-回溯算法part05
    题目:491.递增子序列思路:核心问题——同层去重,这一题不能够重新排序因此不可以用i>index&&nums[i]==nums[i-1]来去重,而是每一层开一个map来判断该数是否出现过代码:var(res[][]intpath[]int)funcfindSubsequences(nums[]int)[][]int{res=make(......
  • Python基础入门学习笔记 050 模块:模块就是程序
    什么是模块•容器->数据的封装•函数->语句的封装•类->方法和属性的封装•模块->模块就是程序命名空间爱的宣言:世界上只有一个名字,使我这样牵肠挂肚,像有一根看不见的线,一头牢牢系在我心尖上,一头攥在你手中,这个名字就叫做鱼C工作室计算机一班的小花……导入模块•......
  • Learn Git in 30 days——第 05 天:了解仓库、工作目录、物件与索引之间的关系
    写的非常好的一个Git系列文章,强烈推荐原文链接:https://github.com/doggy8088/Learn-Git-in-30-days/tree/master/zh-cn在使用Git版本控制的过程中,有些很基本的观念必须被建立,这样才能更有效率也更有意义的学下去。有清楚且正确的观念支持,不但有助于你学习Git指令操作,更重......
  • AOJ0525(bitset, 穷举)
    这题有3点要注意:1.thefliporderisnotrelatedtoresult.2.whywecansimplycounttomaximumofnumbereachcolumn?Imagineonlymanipulatetherow,itiseasytounderstandthatitisunnecessarytoflipthemratherthancountthemaximumside.3.Aga......
  • AOJ0558(cheese, BFS)
    typicalBFSusage:firstuse2array,oneforrecordmap,theotherforshortestpath/flagvisit.BFSfeature:theshortestpathfromonetotheother,justonepoint!!!!(单源路)//#defineLOCAL#include<cstdio>#include<cstring>#include<......