我写了一个用sbt构建的火花流应用程序。它在本地工作得非常好,但是在集群上部署后,它会抱怨我在胖罐中写的一个类(使用jar tvf检查)。以下是我的项目结构。 XXX对象是引发抱怨的对象
src
`-- main
`-- scala
|-- packageName
| `-- XXX object
`-- mainMethodEntryObject
我的提交命令:
$SPARK_HOME/bin/spark-submit \
--class mainMethodEntryObject \
--master REST_URL\
--deploy-mode cluster \
hdfs:///FAT_JAR_PRODUCED_BY_SBT_ASSEMBLY
特定错误消息:
java.lang.NoClassDefFoundError: Could not initialize class XXX
答案 0 :(得分:1)
由于与此用户类似的原因,我遇到了此问题: http://apache-spark-developers-list.1001551.n3.nabble.com/java-lang-NoClassDefFoundError-is-this-a-bug-td18972.html
我在一个对象上调用了一个方法,该对象在对象本身上定义了一些变量,包括spark和logger,就像这样
val spark = SparkSession
.builder()
.getOrCreate()
val logger = LoggerFactory.getLogger(this.getClass.getName)
我正在调用的函数调用另一个函数,该函数调用另一个函数,该函数在rdd上的flatMap
调用内调用另一个函数。
我在堆栈跟踪中得到NoClassDefFoundError
错误,其中堆栈跟踪中的前两个函数调用是类Spark上的函数告诉我不存在。
基于上面链接的对话,我的假设是全局spark
引用在被调用的函数被调用时被初始化(导致{{1例外)。
经过不少实验,我发现这种模式可以解决问题。
NoClassDefFoundError
它有点难看,但Spark似乎喜欢它。
答案 1 :(得分:0)
没有代码很难说,但它看起来像是XXX对象的序列化问题。我不能说我完全理解为什么,但重点是该对象不会被发送给执行者。
对我有用的解决方案是将对象转换为扩展Serializable
的类,并在需要的地方实例化它。所以基本上,如果我没有错,你有
object test {
def foo = ...
}
将在您的主页中用作test.foo
,但您至少需要
class Test extends Serializable {
def foo = ...
}
然后在你的主要开头有val test = new Test
,那就是它。