中间件和业务类加载隔离

Overview

我对类隔离简单的理解:

在一个应用内,有类名为clazz,模块A使用了clazz,模块B也使用了clazz

模块A不会用到模块B ClassLoader加载的clazz,模块B不会用到模块A ClassLoader加载的clazz

例如下图,App用到的中间件依赖了ClassA,App也依赖了ClassA。通过类隔离后,App不会使用用中间件依赖的ClassA,中间件不会使用App依赖的ClassA。

https://i-blog.csdnimg.cn/blog_migrate/c97087f2f3069953d8394f0a83bb6797.png

对于fat jar和业务jar类加载隔离,我们会基于ClassLoader模型来做,但是不会打破这个模型规范。

方案

ClassLoader在加载Java类时,会先从下到上将class交给父classloader加载,如果父classloader无法加载,再从上到下交给子classloader加载。直到某个classloader加载成功或抛出异常。

原始模型

下图是我们平时运行项目时,classloader的上下级关系。应用本身的class和三方包class一般由AppClassLoader加载。

https://i-blog.csdnimg.cn/blog_migrate/9a1911fb4c642ec556f65182bbc6b904.png

中间件本身的类加载脱离AppClassLoader

首先我们退一步,期望中间件的类由单独的classloader加载,中间件依赖的三方包还是由AppClassLoader加载。

对上图的继承关系做一定的修改,添加新的中间件classloaderMiddlewareClassLoader能够加载中间件的jar包(此时还是一个普通的jar)。

AppClassLoader加载中间件class时,先交由MiddlewareClassLoader加载,MiddlewareClassLoader也会交由父classloader加载中间件class,当然他的所有父classloader都是加载不到中间件class的。最后加载流程又回到了MiddlewareClassLoader,它能够加载到中间件classMiddlewareClassLoader将加载到的中间件class返回给AppClassLoader

通过这种方式,中间件本身的类已经由MiddlewareClassLoader加载,和业务AppClassLoader加载隔离了,但是中间件依赖的三方包加载还是通过AppClassLoader完成。

https://i-blog.csdnimg.cn/blog_migrate/edcaf6506833b1ab5a411c1461226431.png

中间件三方依赖和本身类加载脱离AppClassLoader

构建新的classloader继承模型

我们之前将中间件的类和业务的类的classloader做了隔离。根据上面描述的classloader继承关系,做进一步扩展。

下图是抽象出来的新的模型关系。FatJarDelegateClassLoader代替了原来的MiddlewareClassLoaderFatJarDelegateClassLoader管理者多个FatJarClassLoaderFatJarClassLoader对应一个中间件模块。

现在中间件class类加载分为如下步骤:

  1. AppClassLoader开始加载classAppClassLoader委托给父classloader "FatJarDelegateClassLoader" 加载。
  2. FatJarDelegateClassLoader本身不会加载类,而是委派给它管理的FatJarClassLoader
  3. FatJarDelegateClassLoader 内部,还会判断委托加载的类是否为中间件类,如果不是则不会交由管理的FatJarClassLoader加载。否则交给FatJarClassloader加载。

到这里我们做的工作和上图的MiddlewareClassLoader类似,还是没有完全解决三方依赖的问题。

https://i-blog.csdnimg.cn/blog_migrate/275a7da15b5a40a539cc36eec671f3a2.png

修改中间件打包方式

为了解决三方依赖加载隔离,将中间件打包成为fat jar,新的jar包内包含所有的中间件三方依赖。结合上图,每个中间件fat jarFatJarClassloader加载,由于中间件通过FatJarClassloader加载,且它的父classloadernull,那么中间件使用到的三方依赖的类,也会由FatJarClassLoader加载,不会用到业务的类。

FatJarDelegantClassLoader里会判断当前加载的类是否属于中间件,如果不是则不会交由FatJarClassLoader加载,所以应用使用的三方依赖不会用到中间件依赖三方包,做到了中间件依赖和应用依赖隔离。

总结

经过上面几次模型演进,我们可以做到中间件三方包和业务三方包加载隔离,中间件和中间件之间加载隔离。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值