文章篇幅有点长,先一句话总结一下:
在Spring启动过程中,自动注入链路配置;并且利用SpringBoot的EnableAutoConfiguration机制,实现了开发无感知、无代码侵入的zipkin链路跟踪框架
背景
基于zipkin打造的链路跟踪系统上线之后收到了开发同学的好评,尤其是定位跨系统的调用问题时非常方便,效率提升许多。但也有美中不足的地方:第一个版本接入方式是基本上是按照zipkin官方demo进行接入的。这就导致很多地方都需要开发同学进行自行配置、感知到框架底层的东西:如链路上报、采集相关配置以及各种组件需要手动开启,无法做到代码配置无侵入。
具有侵入性且繁杂的配置项会造成很多问题:
- 降低开发同学接入的积极性;
- 不同环境的server配置不一样,每个环境都需要修改,提高了使用成本。
于是下一步的工作重点放到了怎么做才能让开发同学降低接入和使用成本,将链路跟踪打造成基础设施,让上层应用系统接入无感知?
因为zipkin底层技术架构的原因,很难实现skywalking
的模式:将链路跟踪能力下沉到应用运行时环境。
某次阅读师兄代码时,发现师兄使用了BeanPostProcessor这个接口去对spring 容器中的bean进行二次加工处理。突然想到:能否利用BeanPostProcessor在Spring启动的过程中对链路配置进行处理从而实现对中间件的链路跟踪?
银弹:BeanPostProcessor
先看看BeanPostPorcessor
作用的时间点:
再来看看BeanPostProcessor
接口的方法:只有两个方法,分别会在bean初始化之前和之后进行调用
public interface BeanPostProcessor {
/**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
想要在Spring启动过程中启动对中间件的链路跟踪,那么就需要将对应的中间件的配置对象交由Spring进行管理,换句话说就是需要注入到Spring容器中成为一个bean。现在来梳理一下需要追踪的中间件:
- mysql
- dubbo
- incoming http:即对外提供的http接口
- outcoming http:OkHttp、HttpClient、RestTemplate
- 线程池:Executor、ExecutorService、@Scheduled注解
其中mysql、dubbo、incoming http、restTemplate这几个中间件的正常使用方式默认会注入到Spring容器中,处理起来还算方便。
主要的适配工作在HttpClient,有机会单独写一篇文章聊一聊我的适配实现思路。
具体实现
具体的实现逻辑
在Spring启动过程中注入链路跟踪相关配置
继承BeanPostProcessor
接口实现处理链路跟踪配置的ZipkinBeanPostProcessor
:在ZipkinBeanPostProcessor中的postProcessBeforeInitialization或者postProcessBeforeInitialization利用instanceof
关键字对需要进行链路跟踪的中间件配置实例对象进行过滤并进行加工处理;
利用SpringBoot的EnableAutoConfiguration机制,实现无感接入
设置ZipkinConfiguration对properties文件监听以及扫描并注入ZipkinBeanPostProcessor。如何制作spring-boot-starter请参见:SpringBoot 创建自己的 Starter
打好zipkin-spring-boot-starter
jar包以后,SpringBoot应用只需要引入这个starter jar包