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提取出来,进行后续处理
相关推荐
煎鱼eddycjy1 小时前
新提案:由迭代器启发的 Go 错误函数处理
go
煎鱼eddycjy2 小时前
Go 语言十五周年!权力交接、回顾与展望
go
天天扭码3 小时前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
凡人的AI工具箱4 小时前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
运维&陈同学5 小时前
【zookeeper01】消息队列与微服务之zookeeper工作原理
运维·分布式·微服务·zookeeper·云原生·架构·消息队列
不爱说话郭德纲18 小时前
聚焦 Go 语言框架,探索创新实践过程
go·编程语言
码上有前19 小时前
解析后端框架学习:从单体应用到微服务架构的进阶之路
学习·微服务·架构
gjh120821 小时前
什么是微服务?
微服务
问窗1 天前
微服务中Spring boot的包扫描范围
java·spring boot·微服务
聂 可 以1 天前
IDEA一键启动多个微服务
java·微服务·intellij-idea