红魔咖啡馆

头发越掉越多,头发越掉越少

0%

【gRPC】链路追踪

链路追踪

分布式系统中,一次外部请求往往需要多个模块,多个中间件等的相互调用,我们需要搞清楚这一系列调用的先后顺序,性能等信息

这就涉及到了链路追踪,即将一次分布式请求还原成调用链路,将一次分布式请求的调用情况集中显示,他能做到的有:

  • 自动采集数据
  • 分析数据并产生完整调用链
  • 数据可视化

分布式调用链标准

OpenTracing是一个分布式调用链的标准,位于应用程序/类库和日志分析程序之间,用于解决不同的分布式追踪系统API不兼容的问题

数据模型有以下三个:

  • Trace:一个完整的请求链路
  • Span:一次调用过程
  • SpanContext:Trace的全局上下文信息
链路追踪

如图,一次下单的完整请求就是一个Trace,TraceID是请求的全局标识,内部的一次调用被称为一个Span,每个Span都要带上全局的TraceID,这样才能把全局TraceID和每个调用关联起来,这个TraceID需要通过SpanContext传输,遵守协议调用

如何采集

采集信息

可以发现有一个collector负责一种收集数据,每次调用collector会获得如下信息:

  • 全局TraceID:将每个子调用和最初的请求关联
  • SpanID:标记是哪个调用,如图中的0,1,2,1.1
  • ParentSpanID:当前调用的父调用的id ,如b→d的spanid是1.1,则它的parentspanid就是a→b的1,这样可以把两个紧邻的调用关联起来

使用Jaeger实现链路追踪

Jaeger是主流开源链路追踪系统之一

新建Tracer

我们需要生成一个全局Tracer,这个Tracer就是一个Jaeger的实现

使用config.FromEnv()从环境变量中加载一些默认变量,生成配置,需要注意的如下:

  • envServiceName:服务名称
  • envSamplerType:收集器的类型
    • const:固定收集器,根据传入值来指定收集多少请求,范围0-1
    • probabilistic:概率收集器,根据传入值来指定收集请求的概率,范围0-1
    • ratelimiting:每秒最多收集多少请求
    • remote:远端收集器,和概率收集器一样的参数
  • LogSpans:是否输出日志
  • envAgentHostenvAgentPort:Jaeger的代理地址和端口,有默认值

接下来就可以通过cfg.NewTracer(config.Logger(jaeger.StdLogger))启动一个新tracer,若想在某个服务追踪,直接在对应main函数入口处tracing.Init()并传入服务名,设置全局收集器opentracing.SetGlobalTracer(),后面都是通过opentracer的实现控制追踪的开启结束

同样span也可以在方法内部开启,追踪方法间的调用关系和时间

其中这个span属于当前按trace的一个子span,使用child

1
2
3
4
spContext := sp.Context()
    sp = opentracing.StartSpan("queryGoods",
        opentracing.ChildOf(spContext),
    )

常用方法

  • WithFilterFunc():过滤器,指定给予的请求会不会被收集

  • WithTraceHeaderName:metadata传递时用什么header头传递

  • WithTracer:指定tracer,否则使用默认的GlobalTracer

  • WithUnanyRequestHandlerFunc:中间件时使用

  • WithOpName:自定义trace操作的名字