go微服务之链路追踪jaeger

前言

  • 在微服务开发中,经常会有一个接口中先调用A服务再调用B服务,甚至C、D、E服务等多服务调用的情况,这时候如果某个服务出现了问题,我们不知道在哪里断了,或者只能依靠多点日志排查,比较麻烦。这时候链路追踪的优势就出来了。
  • 正常的链路追踪我了解到的Zipkin和Jaeger比较多,我使用的是Jaeger
  • 先实践看下效果再梳理下jaeger的知识点

实践

  • 注册全局的jaeger
go 复制代码
func InitTracing() {
	cfg := jaegerConfig.Configuration{
		ServiceName: "main-client",//服务名字
		Sampler: &jaegerConfig.SamplerConfig{ 
			Type:  jaeger.SamplerTypeRemote,
			Param: 1,//所有的服务都被采样
		},
		Reporter: &jaegerConfig.ReporterConfig{
			LocalAgentHostPort:  "127.0.0.1:6831",
			LogSpans:            true,
			BufferFlushInterval: 5 * time.Second,// 5s提交一次traces
		},
	}
	nativeTracer, closer, err := cfg.NewTracer(jaegerConfig.Logger(jaeger.StdLogger))
	if err != nil {
		logger.Errorf("unable to create jaeger tracer err : %+v\n", err)
		return
	}
	// defer closer.Close()
	opentracing.SetGlobalTracer(nativeTracer) //设置全局tracer
}
  • 注册完之后就是全局的jaeger
  • 可以在调用微服务之前添加链路
go 复制代码
    nativeTrace := opentracing.GlobalTracer() //获取全局的tracer
    span := nativeTrace.StartSpan("mainSpan") //span服务名称
    defer span.Finish()       //延迟释放
    ctx := opentracing.ContextWithSpan(context.Background(), span) //将信息载入上下文
    resp, err := GrpcServer.Create(ctx, &profileRequest)   //将载入信息的上下文传入
    
    // 可以在多处微服务调用的都加上span
    spanA := nativeTrace.StartSpan("artistInfo")
  • 可以在jaegerUI里查看链路信息
  • 完整的链路数据
  • 哪个链路断了可以看出来
  • 可以添加tag 和 log,方便我们排查
go 复制代码
span.SetTag("UpdateStorage", span.Tracer())
span.LogFields(log.String("event", "UpdateStorage"),// 添加log
    log.String("value", in.ArtworkUuid),
)
span.SetTag("storage-update-storage", storageRequest.ArtworkUuid) //设置tag
  • 真实环境下链路数据会不停的刷新,我们可以结合tag进行搜索
  • tagName:tagValue 或者等于号也可以

jaeger知识梳理

jaeger介绍

  • 官方文档,官方文档还有go和java的jaeger初始化代码示例
  • Jaeger 是一个开源的,用于追踪分布式服务间事务的软件。它主要被用来监控和故障排除复杂的微服务环境。Jaeger 使用分布式跟踪来了解不同微服务的请求路径。
  • Jaeger 提供了一个系统用于收集、存储、查询和可视化在微服务间完成一个特定事务时产生的请求数据。这可以帮助开发人员更好地理解他们的软件实现,使用更少的时间寻找和解决问题。
  • jaeger的主要功能
    • 分布式上下文传播:Jaeger 在服务间传播请求上下文,以实现事务跟踪。
    • 存储和检索:Jaeger 收集和存储请求数据,然后提供了一个接口用于查询这些数据。
    • 可视化:Jaeger 提供了一个 Web 界面,用于显示服务间交互的时间序列视图,以助于性能分析和故障排除。

jaeger的知识单元

span基础

  • span 是链路追踪中基本组成要素、一个span表示一个独立的工作单元,比如标识一次函数调用,一次Http请求,span会记录如下基本要素

    • 服务名称 operation name

    • 服务的开始和结束时间

    • kv形式的tags

    • kv形式的logs

    • SpanContext

    • references:该span都一个或多个span的引用

  • Tags

    • 以kv键值对的形式保存用户自定义标签,主要用于链路追踪结果的查询过滤

    • span的tag仅对自己可见,不会随着spancontext传递给后续span

    • 可以在jaeger上进行tag过滤 storage-update-storage=69ca0063-fdf8-49d5-8161-80bc2a19af3411,逗号分隔多条件过滤

  • Logs

    • logs和tags类似,也是kv键值对形式,与tags不同,logs会记录logs的时间,因为logs主要用户记录某些事情发生的时间,logs与key值必须是字符串,value的类型没有限制

SpanContext

  • SpanContext 携带着一些跨服通信的数据,主要包含
    • 足够在系统中标识该span的信息,比如:span_id,trace_id
    • Baggage Items 为整条追踪保存跨服务(跨进程)的kv格式的用户自定义数据
    • Baggage Items 与tag类似,也是kv键值对,与tags不同的是
    • kv 都只能是字符串
    • baggage items 不仅当前span可见,其会随着span contenxt 传给给后续所有的子span,使用baggage items 要注意网络性能和CPU开销

Reference

  • opentracing 定义了两种引用关系ChildOf 和 FollowForm
    • ChildOf :父span的执行依赖子span的执行结果是,此时子span对父span的引用关系是ChildOf,比如对于一次RPC调用,服务端的span 子 span与客户端的span(父span)是ChildOf关系
    • FollowFrom:父span的执行不依赖子span的执行结果,此时子span对父span的引用关系是FollowFrom,FollowFrom常用于异步调用的表示,例如消息队列中的consumer span 与producer span 之间的关系

Trace

  • trace表示一次完整的链路追踪,trace由一个或多个span组成,下入表示了一个由4个span组成的trace

Inject/Extract

  • 为了实现分布式系统中的链路追踪。OpenTracing 提供了 inject、Extract用于- 在请求中注入SpanContext或者从请求中提取出SpanContext
  • 客户端通过Inject将SpanContext注入在载体中,随着请求一起发送到服务端
  • 服务端则通过Extract将SpanContext提取出来,进行后续处理
相关推荐
一直在进步的派大星1 小时前
Docker 从安装到实战
java·运维·docker·微服务·容器
百里守约学编程6 小时前
70. 爬楼梯
算法·leetcode·go
Gogeof7 小时前
云原生化 - 基础镜像(简约版)
微服务·云原生·基础镜像
Gogeof10 小时前
云原生化 - 旅程(简约版)
微服务·云原生
王彬泽10 小时前
【微服务】负载均衡 - LoadBalance(day4)
微服务·负载均衡
编程老船长11 小时前
第24章 Spring Boot RESTful API安全防护:JWT认证实战
spring boot·后端·微服务
Gogeof11 小时前
云原生化 - 工具镜像(简约版)
微服务·云原生·debug·工具
A仔不会笑16 小时前
微服务——分布式事务
分布式·微服务·架构
大宇进阶之路1 天前
docker运行arm64架构的镜像、不同平台镜像构建
docker·微服务·架构
a_ran1 天前
一些 Go Web 开发笔记
后端·golang·go·编程·web·网站