类冲突导致作业执行失败

介绍了 maven 中 exclusion 排包失败,后通过 shade 插件排除成功的例子。

背景

执行hive到sqlserver任务,配置了限流器,报错方法找不到

1
2
3
4
5
6
7
8
Caused by: java.lang.NoSuchMethodError: shade.core.com.google.common.util.concurrent.RateLimiter.acquire()D
at com.dtstack.flinkx.reader.ByteRateLimiter.acquire(ByteRateLimiter.java:79)
at com.dtstack.flinkx.inputformat.BaseRichInputFormat.nextRecord(BaseRichInputFormat.java:280)
at com.dtstack.flinkx.inputformat.BaseRichInputFormat.nextRecord(BaseRichInputFormat.java:66)
at com.dtstack.flinkx.streaming.api.functions.source.DtInputFormatSourceFunction.run(DtInputFormatSourceFunction.java:137)
at org.apache.flink.streaming.api.operators.StreamSource.run(StreamSource.java:100)
at org.apache.flink.streaming.api.operators.StreamSource.run(StreamSource.java:63)
at org.apache.flink.streaming.runtime.tasks.SourceStreamTask$LegacySourceFunctionThread.run(SourceStreamTask.java:201)

分析

看下这个方法com.dtstack.flinkx.reader.ByteRateLimiter#acquire

1
2
3
public void acquire() {
rateLimiter.acquire();
}

这个方法调用了com.google.common.util.concurrent.RateLimiter#acquire()

1
2
3
public double acquire() {
return this.acquire(1);
}

再看下hive reader jar包的情况,也有一个RateLimiter类,但是acquire方法是没有返回值的。

image-20210701145006895

这样看来是hive reader这个插件打包的时候,引入了低版本的guava,导致上面方法找不到错误。

解决

记录下解决过程

对于类冲突,解决思路是:使用maven helper插件分析出引入冲突的依赖,然后在依赖中通过exclusion排除冲突的jar。

排除之后是这样的

image-20210701142900903

重新打包后检查,依然发现旧版的guava包打进来了。

image-20210701145006895

上面不是通过exclusion排除掉了么,为什么还是会有呢?这个问题困扰了几天,中间尝试过通过dependencyManagement锁定版本;在maven-shade-plugin中排除guava包。

转机出现在,既然总会引入一个guava,明确引入一个指定版本的guava包,根据最短路径原则是不是就可以了。

打包时有一段告警

1
2
3
4
5
6
7
8
9
10
11
12
[WARNING] guava-19.0.jar, hive-exec-1.1.1.jar define 1326 overlapping classes: 
[WARNING] - com.google.common.cache.LocalCache$KeyIterator
[WARNING] - com.google.common.collect.ImmutableMapValues$1
[WARNING] - com.google.common.collect.WellBehavedMap$EntrySet$1
[WARNING] - com.google.common.util.concurrent.AbstractService$5
[WARNING] - com.google.common.io.LineProcessor
[WARNING] - com.google.common.io.BaseEncoding$StandardBaseEncoding$2
[WARNING] - com.google.common.collect.ComputingConcurrentHashMap$ComputingSerializationProxy
[WARNING] - com.google.common.reflect.ImmutableTypeToInstanceMap
[WARNING] - com.google.common.io.ByteProcessor
[WARNING] - com.google.common.io.InputSupplier
[WARNING] - 1316 more...

这段告警的意思是说 guava-1.9.0.jar与hive-exec-1.1.1.jar有重叠的类。一下明白了,之前被打进来的guava包来自hive-exec-1.1.1.jar这个包。看样子,通过exclusion并没有排除掉

image-20210701161730196

可行的排除方式是利用maven-shade-plugin插件的filter

image-20210701161849981

最后看下hive-exec-1.1.1.jar中guava是如何打进来的,原来是通过maven-shade-plugin的include引入的。

image-20210701162923474

问题

对于通过maven-shade-plugin插件引入的jar,为什么exclusive就不生效了呢?

参考

用好这几个技巧,解决Maven Jar包冲突易如反掌

[Maven]maven-shade-plugin使用指南

一次Maven依赖冲突踩坑,把依赖调解、类加载彻底整明白了

MAVEN shade 插件解决JAR包冲突

Maven打包之maven-shade-plugin

maven-shade-plugin介绍

解决 jar 包冲突的神器:maven-shade-plugin