当前位置:   article > 正文

Java分布式跟踪系统Zipkin(三):Brave源码分析-Tracing

zipkin trace采样

上一篇博文中,我们了解了Brave框架的基本使用,并且分析了跟Tracer相关的部分源代码。这篇博文我们接着看看Tracing的初始化及相关类的源代码

  1. public class TraceDemo {
  2. public static void main(String[] args) {
  3. Sender sender = OkHttpSender.create("http://localhost:9411/api/v2/spans");
  4. AsyncReporter asyncReporter = AsyncReporter.builder(sender)
  5. .closeTimeout(500, TimeUnit.MILLISECONDS)
  6. .build(SpanBytesEncoder.JSON_V2);
  7. Tracing tracing = Tracing.newBuilder()
  8. .localServiceName("tracer-demo")
  9. .spanReporter(asyncReporter)
  10. .propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "user-name"))
  11. .currentTraceContext(ThreadContextCurrentTraceContext.create())
  12. .build();
  13. Tracer tracer = tracing.tracer();
  14. // ...
  15. }
  16. }

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

Tracing.Builder

  1. public static final class Tracing.Builder {
  2. String localServiceName;
  3. Endpoint localEndpoint;
  4. Reporter<zipkin2.Span> reporter;
  5. Clock clock;
  6. Sampler sampler = Sampler.ALWAYS_SAMPLE;
  7. CurrentTraceContext currentTraceContext = CurrentTraceContext.Default.inheritable();
  8. boolean traceId128Bit = false;
  9. boolean supportsJoin = true;
  10. Propagation.Factory propagationFactory = Propagation.Factory.B3;
  11. public Tracing build() {
  12. if (clock == null) clock = Platform.get();
  13. if (localEndpoint == null) {
  14. localEndpoint = Platform.get().localEndpoint();
  15. if (localServiceName != null) {
  16. localEndpoint = localEndpoint.toBuilder().serviceName(localServiceName).build();
  17. }
  18. }
  19. if (reporter == null) reporter = Platform.get();
  20. return new Default(this);
  21. }
  22. Builder() {
  23. }
  24. }

Tracing中依赖的几个重要类

  • Endpoint – IP,端口和应用服务名等信息
  • Sampler – 采样器,根据traceId来判断是否一条trace需要被采样,即上报到zipkin
  • TraceContext – 包含TraceId,SpanId,是否采样等数据
  • CurrentTraceContext – 是一个辅助类,可以用于获得当前线程的TraceContext
  • Propagation – 是一个可以向数据携带的对象carrier上注入(inject)和提取(extract)数据的接口
  • Propagation.Factory – Propagation的工厂类

前面TraceDemo例子中,我们初始化Tracing时设置了localServiceName,spanReporter,propagationFactory,currentTraceContext 其中spanReporter为AsyncReporter我们上一篇已经分析过其源代码了,在build方法中可以看到,其默认实现是Platform,默认会将Span信息用logger进行输出,而不是上报到zipkin中

  1. @Override public void report(zipkin2.Span span) {
  2. if (!logger.isLoggable(Level.INFO)) return;
  3. if (span == null) throw new NullPointerException("span == null");
  4. logger.info(span.toString());
  5. }

Sampler

采样器,根据traceId来判断是否一条trace需要被采样,即上报到zipkin

  1. public abstract class Sampler {
  2. public static final Sampler ALWAYS_SAMPLE = new Sampler() {
  3. @Override public boolean isSampled(long traceId) {
  4. return true;
  5. }
  6. @Override public String toString() {
  7. return "AlwaysSample";
  8. }
  9. };
  10. public static final Sampler NEVER_SAMPLE = new Sampler() {
  11. @Override public boolean isSampled(long traceId) {
  12. return false;
  13. }
  14. @Override public String toString() {
  15. return "NeverSample";
  16. }
  17. };
  18. /** Returns true if the trace ID should be measured. */
  19. public abstract boolean isSampled(long traceId);
  20. /**
  21. * Returns a sampler, given a rate expressed as a percentage.
  22. *
  23. * <p>The sampler returned is good for low volumes of traffic (<100K requests), as it is precise.
  24. * If you have high volumes of traffic, consider {@link BoundarySampler}.
  25. *
  26. * @param rate minimum sample rate is 0.01, or 1% of traces
  27. */
  28. public static Sampler create(float rate) {
  29. return CountingSampler.create(rate);
  30. }
  31. }

Sampler.ALWAYS_SAMPLE 永远需要被采样 Sampler.NEVER_SAMPLE 永远不采样

Sampler还有一个实现类 CountingSampler可以指定采样率,如CountingSampler.create(0.5f)则对50%的请求数据进行采样,里面用到了一个算法,这里不展开分析了。

TraceContext

包含TraceId,SpanId,是否采样等数据

在Tracer的newRootContext方法中有这样一段代码,通过newBuilder来构建TraceContext对象

  1. TraceContext newRootContext(SamplingFlags samplingFlags, List<Object> extra) {
  2. long nextId = Platform.get().randomLong();
  3. Boolean sampled = samplingFlags.sampled();
  4. if (sampled == null) sampled = sampler.isSampled(nextId);
  5. return TraceContext.newBuilder()
  6. .sampled(sampled)
  7. .traceIdHigh(traceId128Bit ? Platform.get().nextTraceIdHigh() : 0L).traceId(nextId)
  8. .spanId(nextId)
  9. .debug(samplingFlags.debug())
  10. .extra(extra).build();
  11. }

TraceContext中有以下一些属性

  • traceIdHigh – 唯一标识trace的16字节id,即128-bit
  • traceId – 唯一标识trace的8字节id
  • parentId – 父级Span的spanId
  • spanId – 在某个trace中唯一标识span的8字节id
  • shared – 如果为true,则表明需要从其他tracer上共享span信息
  • extra – 在某个trace中相关的额外数据集

还有继承自SamplingFlags的两个属性

  • sampled – 是否采样
  • debug – 是否为调试,如果为true时,就算sampled为false,也表明该trace需要采样(即可以覆盖sampled的值)

TraceContext中还定义了两个接口Inj

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/961962
推荐阅读
相关标签
  

闽ICP备14008679号