最近做项目,在接入flume监控(开源的分布式监控系统)时,发现监控异常,通过排查发现是spring创建代理类DefaultAdvisorAutoProxyCreator和BeanNameAutoProxyCreator的声明顺序不对导致,下面介绍一下问题和解决过程:
1、异常描述:
1.1、异常简述:服务有10台机器,2台机器flume监控正常,8台机器flume有部分方法无法监控。
1.2、异常详情:
(1)服务接入flume监控,上线后发现有8台机器flume监控不完全,漏掉2个方法没有打印监控log。
(2)线上代码和各种配置都统一,也找了维护flume的同学看了下,没有看出flume有异常。
(3)重启服务,情况无变化,正常的2台还是正常,异常的8台还是异常。
(4)测试环境正常。
2、问题排查:
2.1、发现去掉flume监控log,只配本地log,仍然存在此异常。因此怀疑是代理的配置引起的问题。
2.2、flume的代理是DefaultAdvisorAutoProxyCreator,工程中存在另外一个BeanNameAutoProxyCreator代理,用来监控接口耗时。
2.3、这两个代理拦截了一个相同的bean:clearService,flume没有打印监控log的两个方法正好都属于这个bean。
2.4、检查10台线上机器加载这两个代理的顺序,flume正常的机器加载顺序为DefaultAdvisorAutoProxyCreator、BeanNameAutoProxyCreator,异常机器均为BeanNameAutoProxyCreator、DefaultAdvisorAutoProxyCreator。
2.5、在BeanNameAutoProxyCreator声明中加入属性 depends-on=“DefaultAdvisorAutoProxyCreator”,保证DefaultAdvisorAutoProxyCreator代理先实例化。重启服务,发现DefaultAdvisorAutoProxyCreator确实优先实例化,但是flume监控依然异常。怀疑不是实例化顺序的问题。(BeanNameAutoProxyCreator的声明放在DefaultAdvisorAutoProxyCreator前面)
3、解决问题:
保证先加载DefaultAdvisorAutoProxyCreator,再加载BeanNameAutoProxyCreator
3.1、查看源码,发现DefaultAdvisorAutoProxyCreator和BeanNameAutoProxyCreator两个代理都实现了Ordered接口,order值越小执行优先级越高,于是尝试在代理配置中注入order属性。重启服务,flume监控正常。
4、原理、概念介绍:
4.1、depends-on属性:保证当前bean在所依赖的bean初始化之后才初始化。
4.2、BeanPostProcessor接口:在Spring容器完成Bean的初始化前后,添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProcessor接口的实现。比如当Spring容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有 @Autowired 注释时就找到和其匹配(默认按类型匹配)的Bean,并注入到对应的地方中去。
4.3、DefaultAdvisorAutoProxyCreator类:
(1)自动创建代理的类,它会 cahce 容器中所有注册的 advisor, 然后搜索容器中所有的 bean , 如果某个 bean 满足 advisor 中的 Pointcut, 那么将会被自动代理。
(2)实现了BeanPostProcessor和Ordered接口。
(3)它会根据bean的类型判断该bean是否匹配。