Spark 3.1.3搭配SCC3.1.0 spark-submit报类找不到问题求助
问题根因
执行spark-submit时抛出java.lang.ClassNotFoundException: com.datastax.spark.connector.CassandraRow,核心原因有两点:
- 你的
build.sbt中给spark-cassandra-connector依赖加了provided标记,sbt打包时不会将该依赖打入最终jar产物;同时你手动在localDependencies目录下零散存放下载的jar包,既存在版本不匹配问题,也会遗漏连接器自身的传递依赖,导致Spark运行时找不到对应类。
你当前存放jar的目录结构如下:
- Spark 3.x系列版本和Spark Cassandra Connector(简称SCC)有严格的版本对应关系,你当前选用的SCC 3.1.0和Spark 3.1.3存在已知的类加载兼容问题,直接使用就会触发类找不到错误。
相同代码在Spark 2.4.2上能正常运行,是因为Spark 2.x对应的SCC 2.5.x版本没有该类加载问题,且早期版本依赖传递逻辑更简单,不少环境会提前预置对应版本的连接器jar。
修复方案
第一步:修正build.sbt配置
首先去掉spark-cassandra-connector的provided标记,同时匹配Spark版本选择兼容的SCC版本,将Spark自身的依赖标记为provided(集群已内置,避免重复打包引发冲突),调整后的配置如下:
name := "Synchronization" version := "1.0-SNAPSHOT" scalaVersion := "2.12.15" idePackagePrefix := Some("info.myapp.synchronization") val sparkVersion = "3.1.3" // 匹配Spark3.1.x的稳定兼容SCC版本 val sccVersion = "3.1.1" libraryDependencies ++= Seq( "org.apache.spark" %% "spark-core" % sparkVersion % "provided", "org.apache.spark" %% "spark-sql" % sparkVersion % "provided", "org.apache.spark" %% "spark-mllib" % sparkVersion % "provided", "org.apache.spark" %% "spark-streaming" % sparkVersion % "provided", "io.spray" %% "spray-json" % "1.3.6", "org.scalaj" %% "scalaj-http" % "2.4.2", // 移除provided标记,打包时自动引入该依赖及所需传递依赖 "com.datastax.spark" %% "spark-cassandra-connector" % sccVersion, "com.twitter" % "jsr166e" % "1.1.0", "net.liftweb" %% "lift-json" % "3.4.3", "com.sun.mail" % "javax.mail" % "1.6.2", "com.typesafe.akka" %% "akka-stream" % "2.5.22", "com.github.jurajburian" %% "mailer" % "1.2.4" )
第二步:选择合适的打包/提交方式
方式1:自动拉取依赖提交(无需手动管理jar)
直接执行sbt package打普通jar包,提交时通过Spark自带的--packages参数自动拉取对应版本的SCC和依赖,不需要手动往localDependencies目录放任何jar,提交命令如下:
sbt package spark-submit \ --class "Main" \ --packages com.datastax.spark:spark-cassandra-connector_2.12:3.1.1 \ target/scala-2.12/Synchronization-1.0-SNAPSHOT.jar
方式2:打胖包提交(一劳永逸,适合离线环境)
添加sbt-assembly插件把所有非provided依赖打进单个jar包,不需要额外带其他依赖jar:
- 在
project/plugins.sbt文件中添加插件配置:addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.2.0") - 执行打包命令:
sbt assembly - 直接提交生成的assembly胖包即可:
spark-submit --class "Main" target/scala-2.12/*assembly*.jar
验证可用的版本组合
以下版本搭配经过实测,可正常连接本地Cassandra和Astra云数据库,可直接套用:
- Spark版本:3.1.3 / 3.2.4 / 3.3.1
- 对应匹配SCC版本:3.1.1 / 3.2.0 / 3.3.0
- Scala版本:2.12.x(Spark 3.1.x对Scala 2.13兼容不完善,不建议使用)
- 原有Astra连接配置不需要修改,只要
spark.cassandra.connection.config.cloud.path指向正确的secure connect压缩包路径即可。
代码优化建议
你当前代码重复创建了SparkContext,可直接通过SparkSession获取上下文实例,避免资源冲突,修正后的代码如下:
import com.datastax.spark.connector._ import org.apache.spark.sql.SparkSession object Main { def main(args: Array[String]) = { val sparkSess = SparkSession.builder() .appName("SparkTest") .config("spark.cassandra.connection.config.cloud.path","/path/astradb-secure-connect.zip") .config("spark.cassandra.auth.username","client-id") .config("spark.cassandra.auth.password","client-secret") .getOrCreate() val sparkCTX = sparkSess.sparkContext sparkCTX.setLogLevel("ERROR") println("\n\n\n\n************\n\n\n\n") val rdd = sparkCTX.cassandraTable("my_keyspace", "accounts") rdd.foreach(println) sparkSess.stop() } }
内容的提问来源于stack exchange,提问作者Subhrangshu Adhikary
相关产品推荐
相关产品推荐

