AWS EMR Spark Cluster-带Scala fat JAR的步骤,can';找不到主类

AWS EMR Spark Cluster-带Scala fat JAR的步骤,can';找不到主类,scala,jar,executable-jar,amazon-emr,spark-submit,Scala,Jar,Executable Jar,Amazon Emr,Spark Submit,我有一个胖罐子,用Scala编写,由sbt打包。我需要在AWS EMR的火花束中使用它 如果我手动启动集群,将jar复制到主服务器,并使用如下命令运行spark submit作业,它的功能就很好了 spark-submit --class org.company.platform.package.SparkSubmit --name platform ./platform-assembly-0.1.0.jar arg0 arg1 arg2 Exception in thread "main"

我有一个胖罐子,用Scala编写,由sbt打包。我需要在AWS EMR的火花束中使用它

如果我手动启动集群,将jar复制到主服务器,并使用如下命令运行spark submit作业,它的功能就很好了

spark-submit --class org.company.platform.package.SparkSubmit --name platform ./platform-assembly-0.1.0.jar arg0 arg1 arg2
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)
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")
  )
val conf = 
  new SparkConf()
  .setMaster("yarn")
  .setAppName("platform")
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
   {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case _ => MergeStrategy.first
   }
}
但是。。。如果我尝试将其作为一个步骤添加到EMR集群,它将失败。stderr的日志如下所示

spark-submit --class org.company.platform.package.SparkSubmit --name platform ./platform-assembly-0.1.0.jar arg0 arg1 arg2
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)
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")
  )
val conf = 
  new SparkConf()
  .setMaster("yarn")
  .setAppName("platform")
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
   {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case _ => MergeStrategy.first
   }
}
my build.sbt中的相关设置如下所示

spark-submit --class org.company.platform.package.SparkSubmit --name platform ./platform-assembly-0.1.0.jar arg0 arg1 arg2
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)
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")
  )
val conf = 
  new SparkConf()
  .setMaster("yarn")
  .setAppName("platform")
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
   {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case _ => MergeStrategy.first
   }
}
与我的MainClass对应的文件看起来像

package org.company.platform.package

object SparkSubmit {
  def main(args: Array[String]): Unit = {
    // do stuff
  }
}
在EMR控制台中。。。在“添加步骤”对话框中。。。在“参数”框旁边,它说

“这些将传递给JAR中的主函数。如果JAR未在其清单文件中指定主类,则可以指定另一个类名作为第一个参数。”

我想,因为我在build.sbt中指定了一个主类,所以我可以。。。但是它失败了,并且没有记录任何关于失败的信息。如果我尝试将main类指定为第一个参数,它会记录我在上面发布的失败

我认为这可能是一个格式问题,但我无法解决如何解决它,也没有出现任何示例。我已尝试在“添加步骤”对话框中提交以下参数

arg0 arg1 arg2
package.SparkSubmit arg0 arg1 arg2
package/SparkSubmit arg0 arg1 arg2
org.company.platform.package.SparkSubmit arg0 arg1 arg2
也有一些,但都不起作用

版本信息。。。 电子病历4.3 火花1.6 Scala 2.10 sbt 0.13.9

知道我犯了什么愚蠢的错误没有让EMR/Spark找到我的主课吗


谢谢。

编辑-通过解决问题1-6,使其“起作用”,但集群只是坐在那里说它正在“运行”第一步,但从未完成。我错误地将step type设置为“custom jar”而不是“spark application”。在转换之后,我认为只有“问题1”的修复是相关的,而这可能已经修复了我的问题。我不得不撤销对下面问题2、3和5的修复,以使其与“spark应用程序”步骤一起工作,我想我也可以撤销其余的步骤结束编辑

我花了很长时间才让它起作用。我将按顺序发布错误和修复,以防对其他人有用

问题1

无论我作为第一个试图指向MainClass的参数传入什么。。。我也犯了同样的错误。问题出在我的build.sbt中。我(错误地)认为root中的组织和名称足以提供包前缀

我在build.sbt中更改了mainClass,以使文件顶部声明的包与其中的SparkSubmit对象相匹配

mainClass in Compile := Some("org.company.platform.package.SparkSubmit")
然后在“添加步骤”对话框中,我只是输入了参数,没有类名称。。。所以只要“arg0 arg1 arg2”

有趣的参考,如果你想在清单和运行中设置不同的MainClass

问题2

Exception in thread "main" org.apache.spark.SparkException: A master URL must be set in your configuration
我发现这个参考资料

我不知道该用哪一个,但由于EMR使用的是纱线,所以我将其设置为“纱线”这是错误的。在SparkSubmit.main()中,我将主URL设置为如下所示

spark-submit --class org.company.platform.package.SparkSubmit --name platform ./platform-assembly-0.1.0.jar arg0 arg1 arg2
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)
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")
  )
val conf = 
  new SparkConf()
  .setMaster("yarn")
  .setAppName("platform")
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
   {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case _ => MergeStrategy.first
   }
}
问题3

主URL错误消失了,现在这是我的错误

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/spark/SparkConf
在我的构建中。sbt。。。我在libraryDependencies中将spark core和spark sql列为“提供”。。。我不知道为什么这不能作为一个EMR步骤,因为集群已经加载了火花。。。但我把它去掉了,改成了

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合并策略如下所示

spark-submit --class org.company.platform.package.SparkSubmit --name platform ./platform-assembly-0.1.0.jar arg0 arg1 arg2
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)
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")
  )
val conf = 
  new SparkConf()
  .setMaster("yarn")
  .setAppName("platform")
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
   {
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard
    case _ => MergeStrategy.first
   }
}
我将url更改为“本地[2]”

该值没有有效的原因。。。不确定我到底需要多少线程。。。或者这甚至适用于。。。是在主机中,还是在某个虚拟机的某处。。。我不确定。我需要更多地理解这一点,但我只是复制了这里的内容,因为。。。UH为什么不呢

需要了解这里设置了什么

问题6

接下来是大量序列化错误。我不明白为什么,当所有这些代码在手动spark submit或spark shell中运行时没有任何问题。我基本上通过遍历并使每个类扩展为可序列化的来修复它

结束


这就是我的旅程,我得到了一个用scala编写的工作jar,并用sbt编译,作为EMR spark集群中的一个步骤。我希望这能帮助其他人。

我使用SBT(Scala构建工具)处理所有事情,这有一个REPL
sbt控制台
AWS EMR默认没有sbt对吗?我的意思是我们不需要用scala spark的配置来配置它吗?有什么想法吗?为什么不使用EMR的Spark,并使用Spark shell作为Scala REPL?但是,我不太明白你想做什么。本地系统上有一个jar,它是
sbt包的输出
,需要在集群上使用spark submit运行(在集群上,它可以通过scp访问),而且不清楚如何使用jar在AWS EMR中添加步骤