Kitex开发分布式链路追踪 | 青训营

319 阅读3分钟

分布式链路追踪

trace和span概念

学习Jaeger首先需要了解一下teacespan的概念

trace:

在广义上,一个trace代表了一个事务或者流程在(分布式)系统中的整个执行过程,是整个链路视图。trace 是多个 span组成的一个有向无环图(DAG),每一个span代表trace中被命名并计时的连续性的执行片段。

span:

一个Span代表系统中具有开始时间和执行时长的逻辑运行单元。Span之间通过嵌套或者顺序排列建立逻辑因果关系。Span代表整个链路中不同服务内部的视图,所有的span 组合在一起就是整个 trace 的视图。

实践

Jaeger是Uber团队开发分布式链路追踪产品,由GO语言开发,主要由jaeger-client,jaeger-agent,jaeger-collector,storage,jaeger-quer几个部分组成。

简单的运行流程即:client 上报spanagentcollector 收集 agent 的数据(有Push和Pull两种方式),展示到前端WebUI

下面从最简单的例子来入门学习Jager全链路追踪。

创建Trace和上报信息

在原有的Initjaeger中添加修改

func InitJaeger(service string) {
    cfg := &jaegercfg.Configuration{
        ServiceName: service,
        Sampler: &jaegercfg.SamplerConfig{
            Type:  jaeger.SamplerTypeConst,
            Param: 1,
        },
        Reporter: &jaegercfg.ReporterConfig{
            LogSpans:true,
            CollectorEndpoint: "http://127.0.0.1:6831/api/traces",
        },
    }
    //创建一个tracer
    tracer, _, err := cfg.NewTracer(jaegercfg.Logger(jaeger.StdLogger))
    if err != nil {
        panic(fmt.Sprintf("ERROR: cannot init Jaeger: %v\n", err))
    }
    //开启全局追踪
    opentracing.SetGlobalTracer(tracer)
    return
}

tips:设置好GlobalTracer后,需要调用该Tracer的地方如何使用

//返回唯一的全局tracer实例
opentracing.GlobalTracer()

自动链路追踪

  1. 启动类添加

    //配置option
    server.WithSuite(trace.NewDefaultServerSuite()
    
  2. gorm插件接入

    //init.go
    // New constructs a new plugin based opentracing. It supports to trace all operations in gorm,
    // so if you have already traced your servers, now this plugin will perfect your tracing job.
    DB.Use(gormopentracing.New())
    

手动埋点

  1. CreateUserRPC直接Implement中我们埋下rootspan

    span := opentracing.GlobalTracer().StartSpan("CreateUser")
    span.SetTag("root", "this is start")
    //插入span
    ctx = opentracing.ContextWithSpan(ctx, span)
    defer span.Finish()
    
  2. Service业务逻辑层埋点

    //链路追踪埋点
    span, _ := opentracing.StartSpanFromContext(s.ctx, "specify_service")
    span.LogFields(
       log.String("event", "specify_service"),
    )
    defer span.Finish()
    
  3. Query操作埋点

    span, _ := opentracing.StartSpanFromContext(ctx, "QueryUser")
    defer span.Finish()
    
  4. Create操作埋点

    span, _ := opentracing.StartSpanFromContext(ctx, "createUser")
    defer span.Finish()
    

调用接口

image-20230727223720831

jeagerUI查看

自定义埋点image-20230727223956757
跨链路自动trace

image-20230727224434217

Kitex治理特性之可观测性

埋点粒度

Kitex 支持灵活启用基本埋点和细粒度埋点。

埋点粒度:

  1. LevelDisabled 禁用埋点
  2. LevelBase 仅启用基本埋点
  3. LevelDetailed 启用基本埋点和细粒度埋点

埋点策略 & 埋点粒度控制

默认埋点策略:

  1. 无 tracer 时,默认 LevelDisabled
  2. 有 tracer 时,默认 LevelDetailed

客户端埋点粒度控制:

baseStats := client.WithStatsLevel(stats.LevelBase)
client, err := echo.NewClient("echo", baseStats)

服务端埋点力度控制:

baseStats := server.WithStatsLevel(stats.LevelBase)
svr, err := echo.NewServer(baseStats)

埋点说明

基本埋点:

  1. RPCStart,(客户端 / 服务端)RPC 调用开始
  2. RPCFinish,(客户端 / 服务端)RPC 调用结束

细粒度埋点(客户端):

  1. ClientConnStart,连接建立开始
  2. ClientConnFinish,连接建立结束
  3. WriteStart,请求发送(含编码)开始
  4. WriteFinish,请求发送(含编码)结束
  5. ReadStart,响应接收(含解码)开始
  6. WaitReadStart,响应二进制读取开始(仅适用于 Fast Codec
  7. WaitReadFinish,响应二进制读取完毕(仅适用于 Fast Codec
  8. ReadFinish,响应接收(含解码)完毕

细粒度埋点(服务端):

  1. ReadStart,请求接收(含解码)开始
  2. WaitReadStart,请求二进制读取开始(仅适用于 Fast Codec
  3. WaitReadFinish,请求二进制读取完毕(仅适用于 Fast Codec
  4. ReadFinish,请求接收(含解码)完毕
  5. ServerHandleStart,handler 处理开始
  6. ServerHandleFinish,handler 处理完毕
  7. WriteStart,响应发送(含编码)开始
  8. WriteFinish,响应发送(含编码)结束

埋点实验

  • LevelBase

    image-20230727230301114

  • LevelDetailed

    image-20230727230319720