由于微服务的快速迭代、持续集成等特性,越来越多的团队更倾向于它。但是也体现出了一些问题,比如在基础设施建设过程中,需要把通用功能下沉,把现有大而全的基础设施按领域拆分,考虑需要兼容现有生产服务,会产生不同的依赖版本,有时不注意就可以引发问题。比如本文遇到的依赖包版本冲突问题,以及如何利用类隔离技术解决的分析。,类隔离是一种通过类加载器实现加载所需类的实现方式,使得不同版本类间隔离,避免了使用冲突问题,最终的效果就是不同模块的内容被不同的类加载器加载,满足同一环境下同时兼容不同接口实现类。,比如业务服务A和业务服务B均需要消息通知等,均依赖消息中间件,但所引用版本不一致,导致最终只有一个版本加载到JVM,在某一个服务调用时会出现 NoSuchMethodError或NoSuchClassError问题,这就很难排查出来,没准会影响项目进度,最终月度的绩效(“鸡腿”)不保。,服务A pom.xml:,服务B pom.xml:,业务调用流程:,JVM最终加载的为 2.0.0 版本的依赖,导致业务A在调用时抛异常java.lang.NoSuchMethodError。,大体的解决思路就是,在不改变业务代码的前提下, 业务A调用 1.0.0 版本的消息工具类, 业务B调用2.0.0版本的消息工具类,因此需要JVM能够利用自定义类加载器加载所需的类或关联的类。,实现思路,重写 findClass(String name),重写 loadClass(String name),涉及的知识点,重写findClass:,最终结果与预期的结果不一致:,重写loadClass,满足业务A的MessageServiceImpl与MessageUtil由CustomerFindClass加载,注意:这种方式破坏了双亲委托机制,但由于重写了loadClass方法,所有类均会有CustomerFindClass加载器加载,需要过滤出不需要隔离的类,如java.lang包下的类,需要由ExtClassLoader 来加载。,本文分享的方式是从类加载器方向出发,实现最终的类隔离,避免了不同模块间不同类的冲突,其中顺便也简单带过了jvm类加载相关的知识点,也算是一劳多得。
© 版权声明
文章版权归作者所有,未经允许请勿转载。