记一次多个Java Agent同时使用的类增强冲突问题及分析( 四 )


上文经过分析已经找到多个JavaAgent类增强冲突的根因,那么该如何避免此类问题出现呢?这里给出两点较为通用的建议 。
谨慎安排JavaAgent的挂载顺序前面我们提到SkyWalking和自研JavaAgent加载顺序会有不同的结果 。SkyWalking增强时对类的继承关系有修改,而自研JavaAgent则没有,那么该场景将兼容性相对较低的SkyWalking放在前面,兼容性相对较高的自研JavaAgent放在后面,可以暂时规避类增强的冲突问题 。
严格遵守字节码增强的使用要求和限制但是如果我们需要使用3个甚至更多的JavaAgent,上面的方法是治标不治本的 。
无论是Byte Buddy、Javassist还是ASM,底层实现都离不开JDK1.5之后引入的Instrumentation接口 。既然官方接口的设计理念是reTransformClasses()增强类时不能新增、删除或者重命名字段和方法,不能更改方法的签名,也不能更改类的继承关系,那作为JavaAgent的框架开发者 , 应该不要做出超越上述限制的设计,否则极易导致JavaAgent之间的兼容性问题出现 。不仅仅是这个接口,JavaAgent框架的开发者也需要遵循所有的字节码增强的底层接口的设计理念,毕竟有规则才有秩序 。
Sermant避免类增强冲突的实践首先,在自身字节码增强生效的问题上,Sermant严格遵守了上述的字节码增强的官方限制,未改变类的原始继承关系或类方法的签名等,在使用中都未遇到因多个JavaAgent兼容性导致Sermant的字节码增强失效的问题 。只需要把Sermant放在最后挂载,基本可以杜绝上文典型的类增强的冲突问题发生 。
其次,Sermant不仅要保护自身增强不受其他JavaAgent影响,也考虑到避免Sermant对其他JavaAgent的影响 。Sermant计划将premain方法中对第三方依赖的使用进行懒加载 , 将其放置在所有JavaAgent的premain方法执行完成后,main方法执行的初始阶段进行加载 。这样,无论Sermant在多个JavaAgent场景中加载顺序如何,都不会影响其他任何JavaAgent的运行,真正做到不与其他任何JavaAgent发生冲突 。
目前市面上和社区的JavaAgent大都是定位于链路追踪或者应用监控领域,Sermant基于服务治理的自身定位 , 和其他主流JavaAgent不是互相替代的关系,而是友好共存的关系 。使用者挂载多个JavaAgent的场景也许并不少见 , Sermant避免JavaAgent类增强冲突的做法不仅可以保证客户的业务服务可以不受干扰地运用Sermant提供的限流降级、服务注册、负载均衡、标签路由、优雅上下线、动态配置这些微服务治理能力,也能不干扰客户使用的其他JavaAgent按部就班的工作 。
点击关注,第一时间了解华为云新鲜技术~
【记一次多个Java Agent同时使用的类增强冲突问题及分析】

推荐阅读