关于使用Thin Jar提交Spark应用及规避依赖版本异常的技术问询
我来分享下我处理这类Spark提交和依赖问题的实际经验,分两部分来说明:
Thin Jar是Spark官方提供的轻量级提交方案,它不会把所有依赖打包进Jar,而是在运行时自动从Maven仓库拉取所需依赖,非常适合依赖较多或需要灵活切换版本的场景。具体步骤如下:
配置项目构建工具:
如果你用Maven,需要在pom.xml中添加Spark的Maven插件,并指定构建Thin Jar的目标:<plugin> <groupId>org.apache.spark</groupId> <artifactId>spark-maven-plugin</artifactId> <version>${spark.version}</version> <executions> <execution> <goals> <goal>thin-jar</goal> </goals> </execution> </executions> </plugin>注意把集群上的Spark核心依赖(比如
spark-core、spark-sql)的scope设为provided,因为集群环境已经自带这些依赖,不需要打包进去。构建Thin Jar:
在项目根目录执行Maven命令:mvn clean package执行完成后,会在
target目录下生成一个带-thin后缀的Jar包,这就是我们需要的Thin Jar。提交应用到集群:
使用spark-submit命令提交,指定主类和Thin Jar路径即可:spark-submit --class com.your.project.MainClass target/your-project-thin.jar如果你的依赖来自私有Maven仓库,需要通过
--repositories参数指定仓库地址,比如:spark-submit --repositories https://your-private-repo.com/repository/maven-public/ --class com.your.project.MainClass target/your-project-thin.jar
针对Cloudera、Hortonworks这类定制化发行版的依赖兼容性问题,我通常用以下几种方法解决:
对齐集群依赖版本:
本地开发时,直接使用对应发行版提供的依赖坐标,而不是官方的通用版本。比如Cloudera CDH 5.16的Hadoop客户端依赖应该用:<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.6.0-cdh5.16.2</version> <scope>provided</scope> </dependency>同时在Maven的
settings.xml中配置发行版的专属仓库,确保能拉取到正确的依赖包:<repository> <id>cloudera-repos</id> <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url> </repository>排除冲突依赖:
如果项目中的第三方依赖和集群自带的依赖版本冲突(比如Guava、Jackson这类常用库),可以通过spark-submit的--exclude-packages参数排除冲突的包,再用--jars指定你需要的版本:spark-submit --exclude-packages com.google.guava:guava --jars /path/to/your-guava-28.1-jre.jar --class com.your.project.MainClass target/your-project-thin.jar动态拉取所需依赖:
对于项目需要但集群没有的依赖,不用手动打包,直接用spark-submit的--packages参数指定依赖坐标,Spark会自动从Maven仓库拉取并添加到类路径:spark-submit --packages com.databricks:spark-avro_2.12:4.0.0 --class com.your.project.MainClass target/your-project-thin.jar本地模拟集群环境:
为了提前发现兼容性问题,我会用Docker启动对应发行版的最小集群(比如CDH的测试镜像),或者在本地开发环境中配置和集群完全一致的依赖版本,确保本地运行正常后再提交到集群。
这些方法在我处理过的多个Spark项目中都验证有效,能很好地规避依赖缺失或版本冲突导致的异常。
内容的提问来源于stack exchange,提问作者Sumit Khurana

