在本Apache Spark示例教程中,当您的Scala Spark代码未按预期部署时,我们将介绍一些选项。 例如,您的Spark驱动程序是否仅依赖于与Scala 2.11兼容的第三方jar,但您的Spark集群基于Scala 2.10? 也许您的代码依赖于Apache Spark也使用的较新版本的3rd party jar? 或者,也许您希望您的代码使用特定jar的Spark版本,而不是代码指定的jar。
在上述任何一种情况下,您到Spark群集的部署都将不顺利。 因此,在本文中,我们将探讨如何解决所有三个问题。
总览
在本文中,我们将解决三个具体问题,以及如何解决:
- 在Apache Scala 2.11中使用Apache Spark
- 在新版本中覆盖Spark使用的jar
- 为了使用Spark版本,将代码中的jar排除在外
所有这些问题都将根据先前的Spark Streaming教程中使用的Spark Streaming代码解决。 文章末尾提供了源代码下载和截屏视频的链接。
挑战1使用Scala 2.11的Apache Spark
我不知道以下build.sbt文件可能会出错。
带有Scala 2.11的Spark
name := "spark-streaming-example"
version := "1.0"
assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false)
scalaVersion := "2.11.8"
resolvers += "jitpack" at "https://jitpack.io"
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-streaming" % "1.6.1" % "provided",
"org.scalaj" %% "scalaj-http" % "2.3.0",
"org.jfarcand" % "wcs" % "1.5"
)
尽管并没有脱颖而出,但问题出在WebSocket客户端库上。 WebSocket客户端库不适用于编译为Scala 2.10的Apache Spark集群。
发生错误
NoSuchMethodError:scala.Predef $ .ArrowAssoc
Exception in thread "Thread-28" java.lang.NoSuchMethodError: scala.Predef$.ArrowAssoc(Ljava/lang/Object;)Ljava/lang/Object;
at scalaj.http.HttpConstants$.liftedTree1$1(Http.scala:637)
诸如此类的错误表示Scala版本不兼容问题。
wcs被编译为Scala 2.11,并且我找不到在该项目中使用的另一个WebSocket客户端,因此我探索了将Spark编译为Scala 2.11的兼容性。 事实证明,这没什么大不了的。
使用Scala 2.11步骤构建Apache Spark
- 下载源(以下截屏)
- 运行脚本以更改2.11
- 运行make-distribution.sh脚本
这三个步骤的截屏视频:
在截屏中运行的命令:
./dev/change-scala-version.sh 2.11
./make-distribution.sh --name spark-1.6.1-scala-2.11 --tgz -Dscala-2.11 -Pyarn -Phadoop-2.4
创建发行版后,我启动了Spark主服务器和辅助服务器,并乐观地尝试再次部署。 这就是我遇到下一个挑战的方式。
挑战2 Spark和Scala程序之间不兼容的Jar –使用您的Jar
当我尝试将程序集jar部署到为Scala 2.11构建的新的Spark集群自定义程序时,遇到了另一个问题,如以下截屏所示:
正如您在截屏视频中看到的那样,基于Netty的HttpClient中的SSL存在问题。
在问了Googs博士之后,我确定Spark将Akka Actor用于RPC和消息传递,而后者又使用Netty。 事实证明,Netty的Spark / Akka版本与该项目中使用的scalaj-http库所需的版本不兼容。
从命令中调出以下内容:
~/Development/spark-course/spark-streaming $ sbt assembly
[info] Loading project definition from /Users/toddmcgrath/Development/spark-course/spark-streaming/project
[info] Set current project to spark-streaming-example (in build file:/Users/toddmcgrath/Development/spark-course/spark-streaming/)
[info] Including from cache: wcs-1.5.jar
[info] Including from cache: slf4j-api-1.7.12.jar
[info] Including from cache: scalaj-http_2.11-2.3.0.jar
[info] Including from cache: async-http-client-1.9.28.jar
[info] Including from cache: netty-3.10.3.Final.jar
[info] Checking every *.class/*.jar file's SHA-1.
我需要一种方法来配置Spark以使用我的netty-3.10.3.Final.jar而不是Akka中使用的旧版本。
解决方案是使用提供答案的配置变量。 此变量描述为
"Whether to give user-added jars precedence over Spark's own jars when loading classes in the the driver. This feature can be used to mitigate conflicts between Spark's dependencies and user dependencies. It is currently an experimental feature. This is used in cluster mode only."
因此,我尝试使用此conf变量集再次进行部署,如以下屏幕录像所示:
挑战3 Spark和Scala程序之间不兼容的Jar –使用Spark Jar
如果要使用jar而不是Spark版本,该怎么办? 本质上,这与先前描述的挑战2相反。
我查看了输出,并发现slf4j已包含在程序集中。 好了,从日志中,我们可以看到Spark已经在使用slf4j,现在我们的驱动程序正在尝试生成另一个实例。 让我们使用Spark已实例化的slf4j代替。
要从胖罐中删除或排除某些罐,请钩入sbt-assembly插件
使用以下命令更新到build.sbt:
不包括装配罐
excludedJars in assembly <<= (fullClasspath in assembly) map { cp =>
cp filter {
i => i.data.getName == "slf4j-api-1.7.12.jar"
}
}
然后重新运行,您将准备尝试另一次Spark部署。
如您所见,一切正常
结论
这篇文章介绍了使用Scala将Apache Spark部署到Spark集群进行故障排除时的三个挑战和解决方案。 我们介绍了三种情况:
- 带有Scala 2.11的Apache Spark
- 通过从程序集中排除设置Apache Spark jar的优先级
- 使您的jar优先于可比较的Apache Spark版本的jar。
其他参考
http://stackoverflow.com/questions/23330449/how-does-spark-use-netty/23333955#23333955
https://issues.apache.org/jira/browse/SPARK-4738
http://spark.apache.org/docs/latest/configuration.html
http://spark.apache.org/docs/latest/building-spark.html#building-for-scala-211
翻译自: https://www.javacodegeeks.com/2016/05/apache-spark-advanced-cluster-deploy-troubleshooting.html