我有一个用Scala编写的胖罐,由sbt打包。我需要在AWS EMR中的Spark集群中使用它。
如果我手动启动集群,将jar复制到master并使用像这样的命令运行spark-submit作业,它的功能正常...
spark-submit --class org.company.platform.package.SparkSubmit --name platform ./platform-assembly-0.1.0.jar arg0 arg1 arg2
但是......如果我尝试将其添加为EMR集群的一个步骤,它就会失败。 stderr的日志看起来像这样......
Exception in thread "main" java.lang.ClassNotFoundException: package.SparkSubmit
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:278)
at org.apache.hadoop.util.RunJar.run(RunJar.java:214)
at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
我的build.sbt中的相关设置如下所示......
lazy val root = (project in file(".")).
settings(
name := "platform",
version := "0.1.0",
scalaVersion := "2.10.5",
organization := "org.company",
mainClass in Compile := Some("package/SparkSubmit")
)
我的MainClass的相应文件看起来像......
package org.company.platform.package
object SparkSubmit {
def main(args: Array[String]): Unit = {
// do stuff
}
}
在EMR控制台中...在“添加步骤”对话框中...在“参数”框旁边,它显示...
“这些传递给JAR中的main函数。如果JAR没有在其清单文件中指定主类,则可以指定另一个类名作为第一个参数。”
我认为因为我在build.sbt中指定了一个主类,我会没事的......但是它失败了并且没有记录关于失败的任何内容。如果我尝试将主类指定为第一个arg,它会记录我在上面发布的失败。
我认为这可能是格式化问题,但我无法理清如何修复它,也没有任何例子出现。我已经尝试在“添加步骤”对话框中提交以下作为args ...
arg0 arg1 arg2
package.SparkSubmit arg0 arg1 arg2
package/SparkSubmit arg0 arg1 arg2
org.company.platform.package.SparkSubmit arg0 arg1 arg2
其他一些人,但没有任何作用。
版本信息... EMR 4.3 Spark 1.6 斯卡拉2.10 sbt 0.13.9
任何想法,我正在制造的那些愚蠢的错误是不是让EMR / Spark找到我的主要课程?
感谢。
答案 0 :(得分:2)
编辑 - 得到这个"工作"通过制造问题1-6消失,然后集群只是坐在那里说它是"运行"第一步,但它从未完成。我错误地将步骤类型设置为"自定义jar"而不是"火花应用"。切换后,我认为只有问题1"是相关的,仅此一点可能解决了我的问题。我不得不将修复程序退回到下面的问题2,3和5,以使其与#34; spark application"步骤,我怀疑我也可以退出其余部分。 结束编辑
我花了很长时间才开始工作。我会按顺序发布错误和修正,以防其他人在路上行事。
问题1
无论我作为第一个arg尝试并指向MainClass传入的内容......我都得到了同样的错误。问题出在我的build.sbt中。我(错误地)认为root中的组织和名称足以提供包前缀。
我在build.sbt中更改了mainClass,以匹配我在文件顶部声明的包与我的SparkSubmit对象...
mainClass in Compile := Some("org.company.platform.package.SparkSubmit")
然后在"添加步骤"对话框,我刚刚传入args,没有类别指定......所以只是" arg0 arg1 arg2"。
有趣的参考,如果你想在清单和运行中设置不同的MainClass ... How to set main class in build?
问题2
Exception in thread "main" org.apache.spark.SparkException: A master URL must be set in your configuration
我找到了这个参考资料...... https://spark.apache.org/docs/latest/submitting-applications.html#master-urls
我不知道使用哪一个,但由于EMR使用Yarn,我将其设置为" yarn"。 这是错误的。(将其留作生成的后续错误的记录)在SparkSubmit.main()中,我设置了这样的主URL ......
val conf =
new SparkConf()
.setMaster("yarn")
.setAppName("platform")
问题3
主网址错误消失了,现在这是我的错误......
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/spark/SparkConf
在我的build.sbt中......我将spark-core和spark-sql列为"提供"在libraryDependencies ...我不知道为什么这不作为EMR步骤工作,因为群集已加载Spark ...但我删除了它并将其更改为...
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "1.6.0", // % "provided",
"org.apache.spark" %% "spark-sql" % "1.6.0", // % "provided",
...
)
注意 - 删除"提供"我收到了一个新的错误,但是将spark-core和spark-sql的版本更改为1.6.0以匹配EMR 4.3使得它消失了。
问题解决了...创建了新的一个!
问题4
Exception in thread "main" com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'akka.version'
基本上,Akka的reference.conf迷路了。我的build.sbt mergeStrategy看起来像这样......
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
{
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case _ => MergeStrategy.first
}
}
我修改它看起来像这样......
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
{
case "reference.conf" => MergeStrategy.concat
case "application.conf" => MergeStrategy.concat
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case _ => MergeStrategy.first
}
}
问题5
我猜&#34;纱线&#34;问题2中没有正确的选择。我收到了这个错误......
Exception in thread "main" org.apache.spark.SparkException: Could not parse Master URL: 'yarn'
我将网址更改为&#34; local [2]&#34; ...
val conf =
new SparkConf()
.setMaster("local[2]")
.setAppName("starling_for_mongo")
这个价值没有正当理由......不确定我实际需要多少线程......或者甚至应用的地方......是在主人中,还是在某个地方的某个地方......我是...我不确定。需要更多地了解这一点,但我只是复制了这里的内容,因为......呃...为什么不呢? https://spark.apache.org/docs/1.6.1/configuration.html#spark-properties
需要了解此处设置的内容。
问题6
接下来出现了很多序列化错误。我不明白为什么,当所有这些代码运行时没有任何问题,如手动spark-submit或spark-shell。我通过基本上修复它,并使每个类扩展Serializable。
结束
这是我的旅程,获取一个用scala编写的工作jar,并使用sbt编译,以充当EMR spark集群中的一个步骤。我希望这可以帮助其他人。