背景及解决方案

我们假设一个情况,hbase的reader是1.0版本的,hbase的writer是2.0版本的,所以他们依赖的jar包版本也不一致,如果直接一起加载到JVM虚拟机,那就会有jar包的冲突。

image.png

为了避免冲突,就需要给每个插件都设置一个自己的类加载器(类加载的顺序参考之前的jvm - 类的加载),这样不同版本的jar包就不会冲突。

image.png

下面用streamreader的job初始化详细的讲解这个流程。

JarLoader

JarLoader是每个插件的类加载器,为了避免重复的生成,会通过map的形式存放在内存jarLoaderCenter中,key就是plugin.pluginType.pluginName,value就是JarLoader。

pluginType是一个枚举,包括reader、writer、transformer、handler,pluginName就是插件的名称。比如streamreader的key就是plugin.reader.streamreader。

每次获取类加载器的时候,就会从jarLoaderCenter中获取,如果有对应的key-value,就返回JarLoader,如果没有,就创建一个JarLoader,并存入jarLoaderCenter再返回JarLoader。

image.png

JarLoader创建

如果jarLoaderCenter没有对应的JarLoader,就会创建一个JarLoader。

首先是获取路径path,就是读取reader.streamreader的plugin.json配置文件中生成的path信息。

在创建JarLoader的时候,就会把path路径的jar文件以及子路径的jar文件都加入加入到class path中,所以每个插件所需要的jar包在通过JarLoader加载的时候是相互隔离的,这样就避免的jar包冲突。

比如加载的时候,streamreader除了把streamreader-0.0.1-SNAPSHOT.jar加载进来,也会加载libs以下的包。

image.png

ClassLoaderSwapper

由于我们需要在不同的地方使用不同的类加载器,所以在使用之前就需要对类加载器进行切换。

比如当前(用黄色代表)的类加载器是A,我们现在使用类加载B。

image.png

我们首先把当前的类加载器存起来,放入紫色(storeClassLoader)中暂存。然后再把需要使用的类加载B放入黄色中,代表当前使用的类加载是B。

image.png

然后就可以使用B进行类加载,当使用完后,就需要把暂存在紫色的类加载器进行还原。

image.png


大军
847 声望183 粉丝

学而不思则罔,思而不学则殆