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


无论是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按部就班的工作 。
点击关注,第一时间了解华为云新鲜技术~

经验总结扩展阅读