spark添加二方包导致依赖冲突排查
问题描述近期发现了一个线上问题,本地启动byzer服务是正常的,但打好的docker镜像就是抛异常跑不起来,而前几天构建的镜像是正常的,初步定位到时新的发布导致的!于是经过了一系列痛苦的排查。错误堆栈看byzer-lang最近的提交记录都在30天前,显示不会是它的问题,于是根据日志研究。7bafdda4df93] __MMMMMM__ Total jobs: 1 current job:1 jo
问题描述
近期发现了一个线上问题,本地启动byzer服务是正常的,但打好的docker镜像就是抛异常跑不起来,而前几天构建的镜像是正常的,初步定位到时新的发布导致的!于是经过了一系列痛苦的排查。
错误堆栈
看byzer-lang最近的提交记录都在30天前,显示不会是它的问题,于是根据日志研究。
7bafdda4df93] __MMMMMM__ Total jobs: 1 current job:1 job script:load modelList.`` as __output__
22/02/09 14:58:32 ERROR Executor: Exception in task 0.0 in stage 2.0 (TID 2)
java.lang.IllegalArgumentException: Illegal pattern component: XXX
at org.apache.commons.lang3.time.FastDatePrinter.parsePattern(FastDatePrinter.java:282)
at org.apache.commons.lang3.time.FastDatePrinter.init(FastDatePrinter.java:149)
at org.apache.commons.lang3.time.FastDatePrinter.<init>(FastDatePrinter.java:142)
at org.apache.commons.lang3.time.FastDateFormat.<init>(FastDateFormat.java:384)
at org.apache.commons.lang3.time.FastDateFormat.<init>(FastDateFormat.java:369)
at org.apache.commons.lang3.time.FastDateFormat$1.createInstance(FastDateFormat.java:91)
at org.apache.commons.lang3.time.FastDateFormat$1.createInstance(FastDateFormat.java:88)
at org.apache.commons.lang3.time.FormatCache.getInstance(FormatCache.java:82)
报错xxx令人不知所措,一开始怀疑是modelList这个脚本在RestController执行的时候,携带了这个xxx
错误参数,但因为是镜像中不好debug,定位堆栈抛异常的是如下代码:
val jsonDF = limitOrNot {
df.limit(outputSize)
}.toJSON
val scriptJsonStringResult = fetchType match {
case "collect" => jsonDF.collect().mkString(",")
看代码得知是jsonDF.collect().mkString(",")这行的问题,outputSize数据有问题,但我并没有在启动服务的时候请求任何脚本,于是陷入了死胡同。
google后发现是一个spark2普遍的问题,找到如下文章:
https://www.codetd.com/en/article/12490356
https://stackoverflow.com/questions/46429616/spark-2-2-illegal-pattern-component-xxx-java-lang-illegalargumentexception-ill
描述很清晰,是commons-lang3依赖冲突导致的,需要保证commons-lang3依赖在3.5以上。于是顺着这个方向,排了工程里面相关的依赖,本地启动正常,docker中启动报错。。。
于是怀疑是docker环境问题导致,拉取了最新的docker构建脚本,发现大量新增代码,果然是新增代码的锅,新增逻辑比较多,于是直接拉上相关同事一起看。发现最近docker的lib文件夹下增加了很多jar,spark提交任务的脚本增加了很多插件类:
COPY lib/ansj_seg-5.1.6.jar \
lib/nlp-lang-1.7.8.jar \
lib/${AZURE_BLOB_NAME} \
lib/mlsql-assert-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
lib/mlsql-excel-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
lib/mlsql-ext-ets-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
lib/mlsql-shell-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
lib/mlsql-mllib-${MLSQL_SPARK_VERSION}_${SCALA_BINARY_VERSION}-0.1.0-SNAPSHOT.jar \
${MLSQL_HOME}/libs/
spark-submit 任务启动脚本:
$SPARK_HOME/bin/spark-submit --class streaming.core.StreamingApp \ --driver-memory ${DRIVER_MEMORY} \
...
-streaming.plugin.clzznames "tech.mlsql.plugins.ds.MLSQLExcelApp,tech.mlsql.plugins.assert.app.MLSQLAssert,tech.mlsql.plugins.shell.app.MLSQLShell,tech.mlsql.plugins.ext.ets.app.MLSQLETApp"
显然是二方包导致的依赖冲突,而之前花了大量时间改byzer的依赖,打包,部署,重新构建docker都是无用功!
但jar还是比较多,只能穷举的在docker环境中一个一个的删掉,测试是否有启动异常,在排查到AZURE这个jar的时候发现了问题,该jar是我们为了支持AZURE添加的,已经经过冲突依赖shade处理的,shade重构建的项目在这个REPO下:
GitHub - byzer-org/byzer-objectstore-dep
于是clone项目,使用maven Dependency Analyzer分析:
并没有commons-lang3这个依赖,于是怀疑是其他依赖导致的冲突,把azure相关的依赖直接引入到byzer的项目中(为了做依赖冲突分析),于是惊奇的发现commons-lang3又有了:
是因为打包项目为了满足不同的hadoop版本打包,设置了profiles,导致分析工具失效了:
修复问题
对azure-store项目中的依赖做shade处理:
<profile>
<id>shade</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.apache.commons</pattern>
<shadedPattern>shadeio.azure.org.apache.commons</shadedPattern>
</relocation>
<relocation>
<pattern>commons-lang</pattern>
<shadedPattern>shadeio.azure.commons-lang</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
在byzer-lang中添加统一的版本约束:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
</dependencies>
</dependencyManagement>
在启动byzer的子pom中显式声明依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
问题得到解决,另外发现一个问题,虽然dependencyManagement定义版本这种定义方式有如下规范:
-
如果子pom中显式设置了version则以子pom的version为主
-
需要使用父pom依赖时需要声明依赖并且不设置version
但我测试发现在azure这个依赖中携带的commons-lang3即使不在子pom声明使用dependencyManagement定义后,其版本也会被约束成3.10而不是以前的3.3。笔者建议声明一下避免打包解析树的时候出现问题。
更多推荐
所有评论(0)