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提取出来,进行后续处理
相关推荐
童先生24 分钟前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go
幼儿园老大*2 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
想进大厂的小王2 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
九卷技术录2 小时前
(微服务)服务治理:几种开源限流算法库/应用软件介绍和使用
微服务·服务治理·限流算法
阿伟*rui3 小时前
认识微服务,微服务的拆分,服务治理(nacos注册中心,远程调用)
微服务·架构·firefox
想进大厂的小王6 小时前
Spring-cloud 微服务 服务注册_服务发现-Eureka
微服务·eureka·服务发现
架构师那点事儿7 小时前
golang 用unsafe 无所畏惧,但使用不得到会panic
架构·go·掘金技术征文
Gemini199510 小时前
分布式和微服务的区别
分布式·微服务·架构
茶馆大橘18 小时前
微服务系列五:避免雪崩问题的限流、隔离、熔断措施
java·jmeter·spring cloud·微服务·云原生·架构·sentinel
coding侠客19 小时前
揭秘!微服务架构下,Apollo 配置中心凭啥扮演关键角色?
微服务·云原生·架构