sleuth+zipkin核心配置源码解析(七)

源码入口

直接查看sleuth的starter包,找到spring.factories文件,基于springboot的自动配置机制

# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration,\  # trace的基本配置
org.springframework.cloud.sleuth.metric.TraceMetricsAutoConfiguration,\  
org.springframework.cloud.sleuth.log.SleuthLogAutoConfiguration,\     # trace的日志配置
org.springframework.cloud.sleuth.instrument.messaging.TraceSpanMessagingAutoConfiguration,\  # 定义了span的trace信息解析,traceId,parentID之类的
org.springframework.cloud.sleuth.instrument.messaging.TraceSpringIntegrationAutoConfiguration,\ # 定义了和spring-inregration消息集成的管道配置
org.springframework.cloud.sleuth.instrument.messaging.websocket.TraceWebSocketAutoConfiguration,\# websocket配置
org.springframework.cloud.sleuth.instrument.async.AsyncCustomAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.scheduling.TraceSchedulingAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.TraceHttpAutoConfiguration,\  # http请求过来后,trace信息提取,打tag的对象配置
org.springframework.cloud.sleuth.instrument.web.TraceWebAutoConfiguration,\  # 定义了http请求过来后,拦截的filter,拦截器等信息的配置
org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.client.TraceWebAsyncClientAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.zuul.TraceZuulAutoConfiguration,\  # 跟网关集成的配置
org.springframework.cloud.sleuth.instrument.rxjava.RxJavaAutoConfiguration,\  
org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration  # sleuth注解的配置

# Environment Post Processor
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.sleuth.autoconfig.TraceEnvironmentPostProcessor  # 环境变量配置

TraceAutoConfiguration

@Configuration
@ConditionalOnProperty(value="spring.sleuth.enabled", matchIfMissing=true)  
@EnableConfigurationProperties({TraceKeys.class, SleuthProperties.class})
public class TraceAutoConfiguration {
    @Autowired
    SleuthProperties properties;

    @Bean
    @ConditionalOnMissingBean
    public Random randomForSpanIds() {
        return new Random();
    }

    @Bean
    @ConditionalOnMissingBean
    public Sampler defaultTraceSampler() {
        return NeverSampler.INSTANCE;
    }

    @Bean
    @ConditionalOnMissingBean(Tracer.class)
    public DefaultTracer sleuthTracer(Sampler sampler, Random random,
            SpanNamer spanNamer, SpanLogger spanLogger,
            SpanReporter spanReporter, TraceKeys traceKeys) {
        return new DefaultTracer(sampler, random, spanNamer, spanLogger,
                spanReporter, this.properties.isTraceId128(), traceKeys);
    }

    @Bean
    @ConditionalOnMissingBean
    public SpanNamer spanNamer() {
        return new DefaultSpanNamer();
    }

    @Bean
    @ConditionalOnMissingBean
    public SpanReporter defaultSpanReporter() {
        return new NoOpSpanReporter();
    }

    @Bean
    @ConditionalOnMissingBean
    public SpanAdjuster defaultSpanAdjuster() {
        return new NoOpSpanAdjuster();
    }

    @Bean
    @ConditionalOnMissingBean
    public ErrorParser defaultErrorParser() {
        return new ExceptionMessageErrorParser();
    }

}

@ConditionalOnProperty(value=”spring.sleuth.enabled”, matchIfMissing=true) , 匹配spring.sleuth.enabled属性,如果确实,则默认为true。

@EnableConfigurationProperties({TraceKeys.class, SleuthProperties.class}) sleuth的配置文件 , TraceKeys中定义了一系列的tag标签可以,比如http的

,hystrix的,在创建span的tag的时候会使用

defaultTraceSampler() , 当容器中存在这个bean的时候,创建这个bean, 表示是否上报trace信息,默认为NeverSampler.INSTANCE , 一律不上报

sleuthTracer() , 整个系统中的追踪对象,用于创建 span,添加span标签等等。

spanNamer() span名称生成器,这里返回一个DefaultSpanNamer类型的bean,能够实现通过SpanName注解设置span name。

defaultSpanReporter() span的上报器,里面有个report方法, 用于将span信息放入一个阻塞队列里面,之后有一个异步线程去这个队列里面去消费span,然后发送到kafka里面去。 这里默认为NoOpSpanReporter, 即不上报任何信息

defaultSpanAdjuster() span的调整器, 在SpanReporter执行他的report方法的时候,会调用SpanAdjuster的adjust方法 ,默认为NoOpSpanAdjuster , 不做任何调整

@Override
    public void report(Span span) {
        Span spanToReport = span;
        if (spanToReport.isExportable()) {
            try {
                if (this.environment != null) {
                    processLogs(spanToReport);
                }
                // 可以在上报之前对span进行调整
                for (SpanAdjuster adjuster : this.spanAdjusters) {
                    spanToReport = adjuster.adjust(spanToReport);
                }
                this.queue.add(spanToReport);
            } catch (Exception e) {
                this.spanMetricReporter.incrementDroppedSpans(1);
                if (log.isDebugEnabled()) {
                    log.debug("The span " + spanToReport + " will not be sent to Zipkin due to [" + e + "]");
                }
            }
        } else {
            if (log.isDebugEnabled()) {
                log.debug("The span " + spanToReport + " will not be sent to Zipkin due to sampling");
            }
        }
    }

defaultErrorParser() 异常信息解析器

TraceHttpAutoConfiguration

上面讲的TraceAutoConfiguration是sleuth的一些基本配置,大部分都用不到,因为大部分会被扩展。 相信想了解链路追踪系统底层原理的,首先会想到,当一个请求进入我的系统,sleuth是怎么开始处理的, 接下来讲的就是TraceHttpAutoConfiguration , 当http请求进来后,sleuth的一些核心配置,只有有了这些配置,才会更加完善。

扫描二维码关注公众号,回复: 3420741 查看本文章
@Configuration
@ConditionalOnBean(Tracer.class)
@AutoConfigureAfter(TraceAutoConfiguration.class) // 在TraceAutoConfiguration加载完成之后加载
@EnableConfigurationProperties({ TraceKeys.class, SleuthWebProperties.class })
public class TraceHttpAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public HttpTraceKeysInjector httpTraceKeysInjector(Tracer tracer, TraceKeys traceKeys) {
        return new HttpTraceKeysInjector(tracer, traceKeys);
    }

    @Bean
    @ConditionalOnMissingBean
    public HttpSpanExtractor httpSpanExtractor(SleuthWebProperties sleuthWebProperties) {
        return new ZipkinHttpSpanExtractor(Pattern.compile(sleuthWebProperties.getSkipPattern()));
    }

    @Bean
    @ConditionalOnMissingBean
    public HttpSpanInjector httpSpanInjector() {
        return new ZipkinHttpSpanInjector();
    }
}

httpTraceKeysInjector() , 这个类的作用就是给请求添加tag的类,每个span都有tag,这个类的作用就是打tag的 ,代码如下

public void addRequestTags(String url, String host, String path, String method) {
        this.tracer.addTag(this.traceKeys.getHttp().getUrl(), url);
        this.tracer.addTag(this.traceKeys.getHttp().getHost(), host);
        this.tracer.addTag(this.traceKeys.getHttp().getPath(), path);
        this.tracer.addTag(this.traceKeys.getHttp().getMethod(), method);
    }

httpSpanExtractor() 负责解析请求头里面的traceId,parentId ,spanId等,根据提取的信息生成span, 如果http请求中不存在trace信息,那么会创建一个新的span 。 比如: 系统A调用系统 B , 请求刚刚进入A系统的时候,请求头里面是不存在trace信息的,这个时候会创建一个纯新的span, 当请求调用到B系统的时候,这个时候就可以解析出来trace信息,可以解析出来traceId,parentId等信息。

httpSpanInjector() 在发送请求到服务端的时候,会把自身的一些信息放入到请求里面去,也就是客户端请求服务端时,客户端在发起请求之前,会调用这个方法,在请求头里面放入一些信息

public void inject(Span span, SpanTextMap map) {
        Map<String, String> carrier = TextMapUtil.asMap(map);
        this.setHeader(map, carrier, "X-B3-TraceId", span.traceIdString());
        this.setIdHeader(map, carrier, "X-B3-SpanId", span.getSpanId());
        this.setHeader(map, carrier, "X-B3-Sampled", span.isExportable() ? "1" : "0");
        this.setHeader(map, carrier, "X-Span-Name", span.getName());
        this.setIdHeader(map, carrier, "X-B3-ParentSpanId", this.getParentId(span));
        this.setHeader(map, carrier, "X-Process-Id", span.getProcessId());
        Iterator var4 = span.baggageItems().iterator();

        while(var4.hasNext()) {
            Entry<String, String> entry = (Entry)var4.next();
            map.put(this.prefixedKey((String)entry.getKey()), (String)entry.getValue());
        }

 }

上面讲的三个比较重要的对象,都是对span的解析,tag的生成之类的,真正请求进入系统之后,系统怎么处理的配置在哪里呢 ? 下面讲的就是这个。

TraceWebAutoConfiguration

这个配置类里面代码比较多,这里就不一一列出来了,有几个比较重要的点讲一下

/**
     * Nested config that configures Web MVC if it's present (without adding a runtime
     * dependency to it)
     */
    @Configuration
    @ConditionalOnClass(WebMvcConfigurerAdapter.class)
    @Import(TraceWebMvcConfigurer.class)
    protected static class TraceWebMvcAutoConfiguration {
    }

这个空的静态内部类,主要是为了import这个类TraceWebMvcConfigurer 。 这个类继承了WebMvcConfigurerAdapter , 将TraceHandlerInterceptor添加到拦截器列表里面去了

@Bean
    public TraceWebAspect traceWebAspect(Tracer tracer, TraceKeys traceKeys,
            SpanNamer spanNamer, ErrorParser errorParser) {
        return new TraceWebAspect(tracer, spanNamer, traceKeys, errorParser);
    }

定义了Trace的切面

@Bean
    public FilterRegistrationBean traceWebFilter(TraceFilter traceFilter) {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(
                traceFilter);
        filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE,
                REQUEST);
        filterRegistrationBean.setOrder(TraceFilter.ORDER);
        return filterRegistrationBean;
    }

    @Bean
    @ConditionalOnMissingBean
    public TraceFilter traceFilter(BeanFactory beanFactory,
            SkipPatternProvider skipPatternProvider) {
        return new TraceFilter(beanFactory, skipPatternProvider.skipPattern());
    }

定义了TraceFilter , 这个过滤器比较重要,整个调用链的开始就从这里开始的,这里面会解析request里面的信息,创建span之类的,SkipPatternProvider这个对象,是用于过滤有些请求不需要追踪,可以放入到这里面来,到时候就不会创建span了。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/u012394095/article/details/82734435