解读spark添加二方包导致依赖冲突排查问题

 更新时间:2024年06月19日 10:01:05   作者:张哈希  
这篇文章主要介绍了spark添加二方包导致依赖冲突排查问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

问题描述

近期发现了一个线上问题,本地启动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普遍的问题,找到如下文章:


描述很清晰,是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。

笔者建议声明一下避免打包解析树的时候出现问题。

​总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 一文详解Java如何使用commons-csv搞定CSV文件操作

    一文详解Java如何使用commons-csv搞定CSV文件操作

    在 Java 开发中,处理 CSV(逗号分隔值)文件是一项常见的任务,本文将利用Apache Commons CSV 库实现读取,写入和操作CSV文件,希望对大家有所帮助
    2025-02-02
  • Java实现修改PDF文件MD5值且保持内容不变

    Java实现修改PDF文件MD5值且保持内容不变

    在某些场景中,我们可能需要改变PDF文件的MD5值,而又不希望改变文件的可视内容,本文详细介绍了如何实现这一目标,并提供了具体的Java实现示例,需要的可以参考下
    2023-10-10
  • Java中Map.merge()方法使用示例详解

    Java中Map.merge()方法使用示例详解

    这篇文章主要介绍了Map.merge()方法使用和介绍,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • springboot封装JsonUtil,CookieUtil工具类代码实例

    springboot封装JsonUtil,CookieUtil工具类代码实例

    这篇文章主要介绍了springboot封装JsonUtil,CookieUtil工具类过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • Netty通道的容器属性Attribute详解

    Netty通道的容器属性Attribute详解

    这篇文章主要介绍了Netty通道的容器属性Attribute详解,Netty中的Channel通道类,有类似于Map的容器功能,可以通过键值对的形式来保存任何Java Object的值,一般来说可以存放一些与通道实例相关联的属性,比如说服务期端的ServerSession会话实例,需要的朋友可以参考下
    2023-12-12
  • SpringCloud 中使用 Ribbon的方法详解

    SpringCloud 中使用 Ribbon的方法详解

    本文重点给大家介绍SpringCloud 中使用 Ribbon的方法,本文通过实例文字相结合的形式给大家介绍的非常详细,需要的朋友可以参考下
    2018-10-10
  • SpringBoot集成Graphql Query实战示例

    SpringBoot集成Graphql Query实战示例

    这篇文章主要为大家介绍了SpringBoot集成Graphql Query实战示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Java中大数据推荐算法使用场景分析

    Java中大数据推荐算法使用场景分析

    在Java中实现大数据推荐算法时,通常会使用一些开源的机器学习库,如Apache Mahout、Weka、DL4J(DeepLearning4j,用于深度学习)或者Spark MLlib(用于在Spark集群上运行),这篇文章主要介绍了Java中可以用的大数据推荐算法,需要的朋友可以参考下
    2024-06-06
  • 关于ObjectUtils.isEmpty() 和 null 的区别

    关于ObjectUtils.isEmpty() 和 null 的区别

    这篇文章主要介绍了关于ObjectUtils.isEmpty() 和 null 的区别,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Spring系列中的beanFactory与ApplicationContext

    Spring系列中的beanFactory与ApplicationContext

    这篇文章主要介绍了Spring系列中的beanFactory与ApplicationContext,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09

最新评论