分布式跟踪系统学习 zipkin的客户端Brave 分析

Brave源码分析-Tracer和Span

Brave是Java版的Zipkin客户端,它将收集的跟踪信息,以Span的形式上报给Zipkin系统。

Span
首先看下Span的实现类RealSpan

该类依赖几个核心类

Recorder,用于记录Span

Reporter,用于上报Span给Zipkin

MutableSpan,Span的包装类,提供各种API操作Span

MutableSpanMap,以TraceContext为Key,MutableSpan为Value的Map结构,用于内存中存放所有的Span

RealSpan两个核心方法start, finish
分别调用Recorder的start和finish方法,获取跟TraceContext绑定的Span信息,记录开始时间和结束时间,并在结束时,调用reporter的report方法,上报给Zipkin

BoundedAsyncReporter

Reporter的实现类AsyncReporter,而AsyncReporter的实现类是BoundedAsyncReporter

 

BoundedAsyncReporter中的几个重要的类:
- BytesEncoder - Span的编码器,将Span编码成二进制,便于sender发送给Zipkin
- ByteBoundedQueue - 类似于BlockingQueue,是一个既有数量限制,又有字节数限制的阻塞队列
- Sender - 将编码后的二进制数据,发送给Zipkin
- ReporterMetrics - Span的report相关的统计信息
- BufferNextMessage - Consumer,Span信息的消费者,依靠Sender上报Span信息
当messageTimeoutNanos大于0时,启动一个守护线程flushThread,一直循环调用BoundedAsyncReporter的flush方法,将内存中的Span信息上报给Zipkin
而当messageTimeoutNanos等于0时,客户端需要手动调用flush方法来上报Span信息
       而在close方法中将closed变量置为true后,FlushThread中的while循环将结束执行,然后执行finally代码块,系统会将内存中还未上报的Span,添加到queue(result.pending)中。

      前面看到在Recorder的finish方法中,会调用Reporter的report方法,此处report方法,将span转化成字节数组,然后计算出messageSize,添加到queue(pending)中,并记录相应的统计信息。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

flush中大致分下面几步
1. 先将队列pending中的数据,全部提取到BufferNextMessage(bundler)中,直到bundler满为止
2. 当bundler准备好,即isReady()返回true,将bundler中的message全部取出来
3. 将取出来的所有message,调用Sender的sendSpans方法,发送到Zipkin
队列Queue -->  bundler --> zipkin

Brave中各个组件创建大量使用的builder设计模式,Tacing也不例外,先来看下Tracing.Builder

Tracing中依赖的几个重要类
- Endpoint - IP,端口和应用服务名等信息
- Sampler - 采样器,根据traceId来判断是否一条trace需要被采样,即上报到zipkin
- TraceContext - 包含TraceId,SpanId,是否采样等数据
- CurrentTraceContext - 是一个辅助类,可以用于获得当前线程的TraceContext
- Propagation - 是一个可以向数据携带的对象carrier上注入(inject)和提取(extract)数据的接口
- Propagation.Factory - Propagation的工厂类
Sampler还有一个实现类
CountingSampler可以指定采样率,如CountingSampler.create(0.5f)则对50%的请求数据进行采样

分布式跟踪系统学习 zipkin的客户端Brave 分析_第1张图片

Propagation的默认实现是B3Propagation
B3Propagation用下面这些http headers来传播trace信息
- X-B3-TraceId - 128位或者64位的traceId,被编码成32位和16位的小写16进制形式
- X-B3-SpanId - 64位的spanId,被编码成16位的小写16进制形式
- X-B3-ParentSpanId - 64位的父级spanId,被编码成16位的小写16进制形式
- X-B3-Sampled - 1代表采样,0代表不采样,如果没有这个key,则留给header接受端,即服务端自行判断
- X-B3-Flags - debug,如果为1代表采样
inject方法中很简单,就是利用Setter将trace信息设置在carrier中

ExtraFieldInjector的inject方法中,将traceContext的extra数据,set到carrier中,这里的Extra对象,其实就是key-value,有One和Many两种,Many时就相当于Map结构
在Extra中setAll方法中,先用extra的name去nameToKey里找,如果没有就不设置,如果找到就调用setter的put方法将值设置到carrier中。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

你可能感兴趣的:(微服务)