前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >跨服务链路追踪:一次完整的 OpenTelemetry 使用实践

跨服务链路追踪:一次完整的 OpenTelemetry 使用实践

作者头像
运维开发王义杰
发布2023-08-10 14:58:51
发布2023-08-10 14:58:51
2.5K00
代码可运行
举报
运行总次数:0
代码可运行

在现代的微服务架构中,一个用户请求可能需要跨多个服务才能完全处理。这样的复杂性可能会给诊断问题和性能优化带来挑战。因此,跨服务链路追踪技术的应用越来越受到关注。

今天,我们将以一个由 console,sso 和 privilege 三个服务组成的系统为例,探讨如何使用 OpenTelemetry 实现跨服务链路追踪。

一、链路追踪的基本原理

在链路追踪中,我们关注的主要概念是 "Trace" 和 "Span"。Trace 是一个由多个 Span 组成的树状结构,代表一次完整的分布式请求。每个 Span 对应请求在一个服务中的处理过程。每个 Span 有一个唯一的 Span ID,所有 Span 共享一个 Trace ID。

当一个请求从一个服务传递到另一个服务时,Trace ID 和 Parent Span ID 会被包含在请求的元数据中(如 HTTP headers),这样接收请求的服务就知道新的 Span 属于哪个 Trace,以及它的父 Span 是谁。这样就实现了跨服务的请求追踪。

二、在 Go 项目中集成 OpenTelemetry

首先,我们需要在每个服务中初始化 OpenTelemetry。这通常在服务启动时完成。

以下是在 console 服务中初始化 OpenTelemetry 的示例:

代码语言:javascript
代码运行次数:0
运行
复制
package main

import (
  "log"
  
  "go.opentelemetry.io/otel"
  "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
  "go.opentelemetry.io/otel/propagation"
  "go.opentelemetry.io/otel/sdk/resource"
  sdktrace "go.opentelemetry.io/otel/sdk/trace"
  "go.opentelemetry.io/otel/semconv/v1.7.0"
)

func main() {
  ctx := context.Background()
  
  exporter, err := otlptrace.New(ctx,
    otlptrace.WithInsecure(),
    otlptrace.WithEndpoint("localhost:4317"),
  )
  if err != nil {
    log.Fatalf("failed to create exporter: %v", err)
  }
  
  res := resource.NewWithAttributes(
    semconv.SchemaURL,
    semconv.ServiceNameKey.String("console"),
  )

  bsp := sdktrace.NewBatchSpanProcessor(exporter)
  tp := sdktrace.NewTracerProvider(
    sdktrace.WithSpanProcessor(bsp),
    sdktrace.WithResource(res),
  )

  otel.SetTracerProvider(tp)
  otel.SetTextMapPropagator(propagation.TraceContext{})
  
  // Your application code here...
}

这段代码首先创建一个 OTLP exporter,然后创建一个新的 TracerProvider,并设置为全局的 TracerProvider。注意这里我们也设置了 TextMapPropagator 为 TraceContext,这是 W3C 的上下文传播标准。

sso 和 privilege 服务的初始化代码类似,只需要将 semconv.ServiceNameKey.String("console") 中的 "console" 替换为对应的服务名即可。

三、创建和传递 Spans

然后,我们需要在处理请求的每个函数中创建一个新的 Span,并将其传递给后续的处理函数或服务请求。这可以通过 context 完成。

以下是在 console 服务处理请求并调用 sso 服务的示例:

代码语言:javascript
代码运行次数:0
运行
复制
package main

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

func main() {
  tracer := otel.Tracer("console")

  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    ctx, span := tracer.Start(r.Context(), "handleRequest")
    defer span.End()
    
    // Call the sso service
    req, _ := http.NewRequest("GET", "http://localhost:8000/sso", nil)
    
    // Inject the context into the HTTP headers
    otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
    
    http.DefaultClient.Do(req)
  })
  
  http.ListenAndServe(":8000", nil)
}

这段代码首先创建一个新的 Span,并将其添加到当前请求的 context 中。然后,当调用 sso 服务时,将当前 context 注入到新的 HTTP 请求的 headers 中。这样,sso 服务就能获取到包含 Trace ID 和 Parent Span ID 的 context,实现跨服务追踪。

在 sso 和 privilege 服务中的代码类似,只需替换对应的服务名和请求地址。

四、查看追踪结果

最后,我们可以使用 Jaeger 或其他追踪后端查看跨服务的请求链路。只要正确地配置了 OpenTelemetry 和 Jaeger,我们就可以在 web 界面上看到一个请求从发出到完成经过了哪些服务,每个服务处理请求的详细情况。

结语

跨服务链路追踪是一个强大的工具,能够帮助我们理解和优化分布式系统。通过 OpenTelemetry,我们可以方便地在 Go 项目中实现跨服务链路追踪。希望这篇文章能帮助大家更好地理解和应用这个技术。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维开发王义杰 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、链路追踪的基本原理
  • 二、在 Go 项目中集成 OpenTelemetry
  • 三、创建和传递 Spans
  • 四、查看追踪结果
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档