kylin(二)自定义扩展的类加载问题

本文讲述了作者在开发并部署Kylin扩展时遇到的类加载问题,涉及数据源、计算引擎和MapReduce依赖加载。通过深入分析,作者揭示了类加载路径差异导致的构造函数调用失败,并提供了解决方法,包括正确放置jar包和调整类加载路径。
摘要由CSDN通过智能技术生成

在开发完kylin三大框架的扩展代码后,将jar上传放置在kylin中时遇到了一些类加载相关的问题。

1、kylin报错NoSuchMethodException信息,即找不到自定义扩展的数据源。

2021-08-29 18:08:20,811 ERROR [http-bio-7070-exec-10] source.SourceManager:118 : Failed to create source: SourceType=0
java.lang.NoSuchMethodException: com.wyt.source.KylinSource.<init>(org.apache.kylin.common.KylinConfig)
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getDeclaredConstructor(Class.java:2178)
    at org.apache.kylin.source.SourceManager.createSource(SourceManager.java:115)
    at org.apache.kylin.source.SourceManager.getCachedSource(SourceManager.java:84)
    at org.apache.kylin.source.SourceManager.getSource(SourceManager.java:126)
    at org.apache.kylin.rest.service.JobService.submitJobInternal(JobService.java:253)
    at org.apache.kylin.rest.service.JobService.submitJob(JobService.java:226)
    at org.apache.kylin.rest.controller.CubeController.buildInternal(CubeController.java:402)
    at org.apache.kylin.rest.controller.CubeController.rebuild(CubeController.java:362)

追踪源码,定位到如下代码:

private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
                                        int which) throws NoSuchMethodException
    {
        Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
        for (Constructor<T> constructor : constructors) {
            if (arrayContentsEq(parameterTypes,
                                constructor.getParameterTypes())) {
                return getReflectionFactory().copyConstructor(constructor);
            }
        }
        throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
    }

我把开发好的jar放置在kylin根目录下的ext文件夹里面。debug情况如下图:

能进入该方法中,说明类肯定已经存在,此时在比较存在类中的构造器参数类型和已有的参数类型是否匹配,如果匹配就正常返回,如果不匹配就抛出上面看到的异常。

参数类型都是KylinConfig,包名类型都一样,但是结果却是两个参数类型不匹配。这说明他们的类加载肯定不同,即运行时包不同(不清楚的可以上网查查运行时包、命令空间一类的定义)。parameterTypes类加载情况如下(它主要加载的是/WEB/lib目录下的包):

constructor.getParameterTypes的类加载如下:

对比可以发现源码中KylinConfig与开发包中KylinConfig对应的类加载器不同,而源码默认的类加载器加载路径是 {kylin-home}/tomcat/webapps/kylin/WEB-INF/lib/。

所以将包重放置到lib目录后解决了上述问题(因为类加载是服务启动时做的事情,所以在移动包之后要重启下kylin才能生效)。

2、报错信息

Error: java.lang.IllegalArgumentException: Implementations missing, ID 2, interface org.apache.kylin.engine.IBatchCubingEngine
	at org.apache.kylin.common.util.ImplementationSwitch.get(ImplementationSwitch.java:77)
	at org.apache.kylin.engine.EngineFactory.batchEngine(EngineFactory.java:42)
	at org.apache.kylin.engine.EngineFactory.getJoinedFlatTableDesc(EngineFactory.java:52)
	at org.apache.kylin.engine.mr.MRUtil.getBatchCubingInputSide(MRUtil.java:42)
	at org.apache.kylin.engine.mr.steps.FactDistinctColumnsMapperBase.doSetup(FactDistinctColumnsMapperBase.java:77)
	at org.apache.kylin.engine.mr.steps.FactDistinctColumnsMapper.doSetup(FactDistinctColumnsMapper.java:83)
	at org.apache.kylin.engine.mr.KylinMapper.setup(KylinMapper.java:48)
	at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:143)
首先定位到源码位置如下:

这个方法会抛出两种异常,异常内容比较相似,所以具体分析时一定要定位好是哪出问题。本报错中出问题的地方在末尾,说明获取到了要加载的类名称,即kylin加载了我们的扩展包,但是实例化失败了。没什么头绪,于是我在构建的时候debug源码追踪了一下,截图如下:
可以看到kylin源码中显示这一块没问题,是可以正常实例化的。这一下给我整懵了,于是我再次回头仔细看了下日志,发现这个报错来自于mapreduce,详情如下:
所以推测可能是mapreduce找不到我们的扩展包,查找资料发现kylin运行mapreduce任务默认会从本地加载需要的依赖包,而且在kylin.log中也有提示:
2021-08-29 20:35:37,542 INFO  [Scheduler 729395435 Job a1147e90-2f08-b987-8a50-60151a8b72ef-92] common.AbstractHadoopJob:227 : Didn't find mapreduce.application.classpath in job configuration, will run 'mapred classpath' to get the default value。
即不主动指定mapreduce加载路径的情况下,会去取本地的默认值(这行日志后一般会打印出从本地加载的jar信息),于是我把扩展包又放了一份在mapreduce的目录下:{hadoop-home}/share/hadoop/mapreduce/lib (直接放mapreduce会报错)。

再次启动,项目运行正常(每次mapreduce任务都会加载,所以不需要重启kylin或者hadoop)

3、小结

上面两个问题是我在3.1.0版本遇到的问题,而在3.1.0版本如果想自定义扩展kylin功能,在开发完打包上传时至少要传到两个目录下才行。

如果想了解具体如何扩展kylin的数据源、计算引擎、存储源三大框架,可以参考我的这篇文章:kylin扩展数据源、计算引擎、存储框架源码_java实现 kylin 不同的数据源_Interest1_wyt的博客-CSDN博客
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值