4. 分布式链路追踪客户端工具包Starter设计

05-13 1613阅读

前言

本文将从零搭建分布式链路追踪客户端工具包的Starter,并将在后续文章中逐步丰富支持的场景。这里首先将搭建一个最基础的Starter,能提供的功能和1. 看完这篇文章我奶奶都懂Opentracing了一文中的示例demo类似。

相关版本依赖如下。

opentracing-api版本:0.33.0

opentracing-spring-web版本:4.1.0

jaeger-client版本:1.8.1

Springboot版本:2.7.6

github地址:honey-tracing

正文

一. 基础Starter实现

在基础Starter中,主要是提供Servlet的过滤器和RestTemplate的拦截器,我们后续的复杂功能,就将在这个基础Starter上一点一点的丰富。

首先下图是Starter的工程结构。

4. 分布式链路追踪客户端工具包Starter设计

在基础Starter中,Servlet的链路过滤器实现如下。

public class HoneyTracingFilter implements Filter {
    private final Tracer tracer;
    public HoneyTracingFilter(Tracer tracer) {
        this.tracer = tracer;
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        SpanContext extractedSpanContext = tracer.extract(Format.Builtin.HTTP_HEADERS,
                new HttpServletRequestExtractAdapter(request));
        Span span = tracer.buildSpan(request.getMethod())
                .asChildOf(extractedSpanContext)
                .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
                .start();
        try (Scope scope = tracer.activateSpan(span)) {
            filterChain.doFilter(servletRequest, servletResponse);
        } catch (IOException | ServletException e) {
            Tags.ERROR.set(span, Boolean.TRUE);
            throw e;
        } finally {
            span.finish();
        }
    }
}

RestTemplate的链路拦截器实现如下。

 * RestTemplate客户端的分布式链路追踪拦截器。
 */
public class HoneyRestTemplateTracingInterceptor implements ClientHttpRequestInterceptor {
    private final Tracer tracer;
    public HoneyRestTemplateTracingInterceptor(Tracer tracer) {
        this.tracer = tracer;
    }
    @NotNull
    public ClientHttpResponse intercept(@NotNull HttpRequest request, @NotNull byte[] body,
                                        ClientHttpRequestExecution execution) throws IOException {
        Span span = tracer.buildSpan(HONEY_REST_TEMPLATE_NAME)
                .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
                .start();
        tracer.inject(span.context(), Format.Builtin.HTTP_HEADERS, new HttpHeadersCarrier(request.getHeaders()));
        try (Scope scope = tracer.activateSpan(span)) {
            return execution.execute(request, body);
        } catch (IOException e) {
            Tags.ERROR.set(span, Boolean.TRUE);
            throw e;
        } finally {
            span.finish();
        }
    }
}

打印链路日志的HoneySpanReporter目前不打印任何日志,后面再添加打印逻辑,实现如下。

public class HoneySpanReporter implements Reporter {
    public void report(JaegerSpan span) {
        
        
    }
    public void close() {
    }
}

我们使用HoneyTracingProperties来读取链路相关的配置,目前仅读取一个开关enabled,如下所示。

 * 分布式链路追踪配置属性类。
 */
@ConfigurationProperties("honey.tracing")
public class HoneyTracingProperties {
    private boolean enabled;
    public boolean isEnabled() {
        return enabled;
    }
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}

使用到的一些常量,存放在CommonConstants中,如下所示。

public class CommonConstants {
    public static final double DEFAULT_SAMPLE_RATE = 1.0;
    public static final String HONEY_TRACER_NAME = "HoneyTracer";
    public static final String HONEY_REST_TEMPLATE_NAME = "HoneyRestTemplate";
    public static final String ALL_URL_PATTERN_STR = "/*";
}

再接下来就是三个自动装配类,其中HoneyRestTemplateTracingConfig负责注册HoneyRestTemplateTracingInterceptor给容器中所有的RestTemplate,HoneyTracingConfig负责注册Tracer到Spring容器,HoneyTracingFilterConfig负责注册HoneyTracingFilter,实现如下所示。

 * RestTemplate分布式链路追踪配置类。
 */
@ConditionalOnBean(RestTemplate.class)
@Configuration
@AutoConfigureAfter(HoneyTracingConfig.class)
public class HoneyRestTemplateTracingConfig {
    public HoneyRestTemplateTracingConfig(List restTemplates, Tracer tracer) {
        for (RestTemplate restTemplate : restTemplates) {
            
            restTemplate.getInterceptors().add(new HoneyRestTemplateTracingInterceptor(tracer));
        }
    }
}
 * 分布式链路追踪配置类。
 */
@Configuration
@EnableConfigurationProperties({HoneyTracingProperties.class})
@ConditionalOnProperty(prefix = "honey.tracing", name = "enabled", havingValue = "true", matchIfMissing = true)
public class HoneyTracingConfig {
    @Bean
    @ConditionalOnMissingBean(Sampler.class)
    public Sampler sampler() {
        return new ProbabilisticSampler(DEFAULT_SAMPLE_RATE);
    }
    @Bean
    @ConditionalOnMissingBean(Reporter.class)
    public Reporter reporter() {
        return new HoneySpanReporter();
    }
    @Bean
    @ConditionalOnMissingBean(Tracer.class)
    public Tracer tracer(Sampler sampler, Reporter reporter) {
        return new JaegerTracer.Builder(HONEY_TRACER_NAME)
                .withTraceId128Bit()
                .withZipkinSharedRpcSpan()
                .withSampler(sampler)
                .withReporter(reporter)
                .build();
    }
}
 * Servlet过滤器配置类。
 */
@Configuration
@AutoConfigureAfter(HoneyTracingConfig.class)
public class HoneyTracingFilterConfig {
    @Bean
    public FilterRegistrationBean honeyTracingFilter(Tracer tracer) {
        HoneyTracingFilter honeyTracingFilter = new HoneyTracingFilter(tracer);
        FilterRegistrationBean filterFilterRegistrationBean
                = new FilterRegistrationBean(honeyTracingFilter);
        filterFilterRegistrationBean.addUrlPatterns(ALL_URL_PATTERN_STR);
        return filterFilterRegistrationBean;
    }
}

最后就是spring.factories和pom文件,内容如下所示。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 com.honey.tracing.config.HoneyTracingConfig,\
 com.honey.tracing.config.HoneyTracingFilterConfig,\
 com.honey.tracing.config.HoneyRestTemplateTracingConfig

    
        honey-tracing
        com.honey
        1.0-SNAPSHOT
    
    4.0.0
    honey-starter-tracing
    
        8
        8
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-configuration-processor
        
        
            io.opentracing
            opentracing-api
            provided
        
        
            io.opentracing.contrib
            opentracing-spring-web
            provided
        
        
            io.jaegertracing
            jaeger-client
            provided
        
    
    
        
            
                org.apache.maven.plugins
                maven-source-plugin
                
                    
                        attach-sources
                        
                            jar
                        
                    
                
            
        
    

还有一点要补充,父工程的pom文件如下所示。


    4.0.0
    pom
    
        org.springframework.boot
        spring-boot-starter-parent
        2.7.6
    
    com.honey
    honey-tracing
    1.0-SNAPSHOT
    
        
            
                io.opentracing
                opentracing-api
                0.33.0
            
            
                io.opentracing.contrib
                opentracing-spring-web
                4.1.0
            
            
                io.jaegertracing
                jaeger-client
                1.8.1
            
        
    
    
        honey-starter-tracing
        honey-tracing-example
    

二. 测试demo搭建

我们需要一个demo来测试我们的基础Starter,并且随着后续Starter支持的功能的增多,我们的demo也要相应的扩展更多的场景。

首先是demo的目录结构,如下所示。

4. 分布式链路追踪客户端工具包Starter设计

1. example-service-1

RestTemplateConfig简单的向Spring容器注册了一个RestTemplate的bean,如下所示。

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

RestTemplateController提供了发送接口,如下所示。

@RestController
public class RestTemplateController {
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/send")
    public void send(String url) {
        restTemplate.getForEntity(url, Void.class);
    }
}

最后是application.yml和pom文件,如下所示。

server:
  port: 8080

    
        honey-tracing-example
        com.honey
        1.0-SNAPSHOT
    
    4.0.0
    example-service-1
    
        
            com.honey
            honey-starter-tracing
            1.0-SNAPSHOT
        
        
            io.opentracing
            opentracing-api
            0.33.0
        
        
            io.opentracing.contrib
            opentracing-spring-web
            4.1.0
        
        
            io.jaegertracing
            jaeger-client
            1.8.1
        
        
            org.projectlombok
            lombok
        
    

2. example-service-2

RestTemplateController提供了接收接口,如下所示。

@RestController
public class RestTemplateController {
    @GetMapping("/receive")
    public void receive() {
        System.out.println();
    }
}

最后是application.yml和pom文件,如下所示。

server:
  port: 8081

    
        honey-tracing-example
        com.honey
        1.0-SNAPSHOT
    
    4.0.0
    example-service-2
    
        
            com.honey
            honey-starter-tracing
            1.0-SNAPSHOT
        
        
            io.opentracing
            opentracing-api
            0.33.0
        
        
            io.opentracing.contrib
            opentracing-spring-web
            4.1.0
        
        
            io.jaegertracing
            jaeger-client
            1.8.1
        
        
            org.projectlombok
            lombok
        
    

总结

在本文,首先实现了一个基础的Starter包,为分布式链路追踪提供了Servlet过滤器和RestTemplate拦截器,其次实现了一个demo,后续分布式链路追踪Starter的功能,将用该demo完成测试。

原文:https://juejin.cn/post/7337216565097562149

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]