链路追踪
分布式系统中,一次外部请求往往需要多个模块,多个中间件等的相互调用,我们需要搞清楚这一系列调用的先后顺序,性能等信息
这就涉及到了链路追踪,即将一次分布式请求还原成调用链路,将一次分布式请求的调用情况集中显示,他能做到的有:
- 自动采集数据
- 分析数据并产生完整调用链
- 数据可视化
分布式调用链标准
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:是否输出日志envAgentHost和envAgentPort: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,否则使用默认的GlobalTracerWithUnanyRequestHandlerFunc:中间件时使用WithOpName:自定义trace操作的名字