Spark集群模式下Gson版本冲突问题排查与解决求助
问题核心
Spark集群模式中,Driver和Executor会优先加载自带的Gson 2.2.4,而你的自定义服务依赖的kubernetes-client 19.0.1强制要求Gson 2.10.1,常规的依赖排除、Shading打包、userClasspathFirst配置可能因细节没处理到位导致失效,以下是针对性的解决方法:
1. 修正Shading配置(最可靠方案)
之前的Shading可能没覆盖所有Gson相关依赖路径,或未正确关联kubernetes-client的依赖传递。在sbt-assembly中配置完整的包重命名规则,彻底隔离Spark自带Gson与项目依赖的高版本Gson:
// build.sbt 中添加assembly配置 assemblyShadeRules in assembly := Seq( // 将所有Gson相关包路径重命名为shaded前缀 ShadeRule.rename("com.google.gson.**" -> "shaded.com.google.gson.@1") .inLibrary("com.google.code.gson" % "gson" % "2.10.1") .inLibrary("io.kubernetes" % "client-java" % "19.0.1") .inProject // 确保项目代码中引用的Gson也指向重命名后的包 ) // 依赖配置中彻底排除Spark组件自带的Gson libraryDependencies ++= Seq( "org.apache.spark" %% "spark-sql" % sparkVersion % Provided exclude("com.google.code.gson", "gson"), "com.datastax.spark" %% "spark-cassandra-connector" % connectorVersion % Provided exclude("com.google.code.gson", "gson"), "io.kubernetes" % "client-java" % "19.0.1" exclude("com.google.code.gson", "gson"), "com.google.code.gson" % "gson" % "2.10.1" )
说明:该配置会把所有依赖中的com.google.gson路径替换为shaded.com.google.gson,让项目依赖的Gson与Spark自带版本完全隔离,避免类加载冲突。
2. 集群级类加载策略补全
如果Shading后仍有问题,可能是集群启动参数未正确生效,需在提交任务时明确指定Driver和Executor的类加载优先级:
完整Spark提交命令示例:
spark-submit \ --class com.your.package.MainClass \ --master yarn \ --deploy-mode cluster \ --driver-user-class-path-first \ --conf spark.executor.userClassPathFirst=true \ your-shaded-assembly.jar
注意:部分集群可能因安全策略禁用userClassPathFirst,该方法仅作为Shading方案的补充,优先推荐Shading。
3. 检查Dependencies.scala的依赖排除是否彻底
确保所有Spark相关依赖都完全排除Gson,避免打包时混入旧版本:
// Dependencies.scala 示例配置 object Dependencies { val sparkVersion = "3.3.0" val connectorVersion = "3.3.0" val sparkSql = "org.apache.spark" %% "spark-sql" % sparkVersion % Provided excludeAll( ExclusionRule(organization = "com.google.code.gson") ) val sparkCassandraConnector = "com.datastax.spark" %% "spark-cassandra-connector" % connectorVersion % Provided excludeAll( ExclusionRule(organization = "com.google.code.gson") ) val k8sClient = "io.kubernetes" % "client-java" % "19.0.1" excludeAll( ExclusionRule(organization = "com.google.code.gson") ) val gson = "com.google.code.gson" % "gson" % "2.10.1" val allDependencies = Seq(sparkSql, sparkCassandraConnector, k8sClient, gson) }
验证方法
打包完成后,执行jar tf your-assembly.jar命令,确认存在shaded/com/google/gson路径,且无原生com/google/gson路径(Spark的Provided依赖不会被打包进jar,因此无需担心)。同时确保项目代码中若直接引用Gson,导入的是shaded.com.google.gson包。
内容的提问来源于stack exchange,提问作者Jelly

