Scala版本
。所有软件包都必须使用相同的主要(2.10、2.11、2.12)Scala版本。
build.sbt
:构建和部署Spark应用程序时的常见问题是:
java.lang.ClassNotFoundException
。object x is not a member of package y
编译错误。java.lang.NoSuchMethodError
如何解决这些问题?
Apache Spark的类路径是动态构建的(以适应每个应用程序的用户代码),这使其容易受到此类问题的影响。 @user7337271的答案是正确的,但是还有更多的问题,这取决于您使用的集群管理器(“主服务器”)。
首先,Spark应用程序由这些组件组成(每个组件都是一个单独的JVM,因此可能在其类路径中包含不同的类):
SparkSession
(或SparkContext
)并连接到集群管理器以执行实际的工作这些关系之间的关系在此图中来自Apache Spark的cluster mode overview:
现在-哪些类应该驻留在每个组件中?
这可以通过下图来回答:
让我们慢慢解析:
Spark Code
是Spark的库。它们应该存在于[[ALL三个组件中,因为它们包含让我们Spark在它们之间进行通信的胶水。顺便说一下,Spark作者做出了一个设计决策,即在所有组件中都包含所有组件的代码(例如,也应只在驱动程序的Executor中运行的代码)以简化此操作-因此,Spark的“胖罐”(版本不超过1.6) )或“归档”(在2.0中,详细信息如下)包含所有组件的必要代码,并且在所有组件中都应可用。仅驱动程序代码
Distributed Code
如何
Spark Code
:如先前的回答所述,您必须在所有组件中使用相同的Scala和Spark版本。Standalone
模式下,存在一个“现有” Spark安装,应用程序(驱动程序)可以连接到该安装。这意味着所有驱动程序必须使用相同的Spark版本在主服务器和执行程序上运行。1.2在YARN / Mesos
中,每个应用程序可以使用不同的Spark版本,但是同一应用程序的所有组件必须使用相同的版本。这意味着,如果您使用版本X来编译和打包驱动程序应用程序,则在启动SparkSession时应提供相同的版本(例如,使用YARN时通过spark.yarn.archive
或spark.yarn.jars
参数)。您提供的jar /档案文件应包含所有Spark依赖项(包括传递性依赖项>>),并且在应用程序启动时,它将由集群管理器运送到每个执行程序。驱动程序代码
:完全取决于-驱动程序代码可以一堆jar或“胖罐”的形式运送,只要它包含所有Spark依赖项和所有用户代码Distributed Code
spark.jars
参数完成的。总结
,这是构建和部署Spark应用程序的建议方法(在这种情况下-使用YARN):spark.jars
时,将正确的分布式代码版本作为SparkSession
参数的值传递>lib/
文件夹下包含所有jar的存档文件(例如gzip)的位置作为spark.yarn.archive
的值传递Scala版本
build.sbt
:name := "Simple Project"
version := "1.0"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % "2.0.1",
"org.apache.spark" % "spark-streaming_2.10" % "2.0.1",
"org.apache.bahir" % "spark-streaming-twitter_2.11" % "2.0.1"
)
我们为Scala 2.10使用spark-streaming
,而其余软件包则为Scala 2.11。有效
文件可能是
name := "Simple Project"
version := "1.0"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % "2.0.1",
"org.apache.spark" % "spark-streaming_2.11" % "2.0.1",
"org.apache.bahir" % "spark-streaming-twitter_2.11" % "2.0.1"
)
但是最好是全局指定版本并使用%%
(为您添加scala版本):
name := "Simple Project" version := "1.0" scalaVersion := "2.11.7" libraryDependencies ++= Seq( "org.apache.spark" %% "spark-core" % "2.0.1", "org.apache.spark" %% "spark-streaming" % "2.0.1", "org.apache.bahir" %% "spark-streaming-twitter" % "2.0.1" )
类似地在Maven:
<project>
<groupId>com.example</groupId>
<artifactId>simple-project</artifactId>
<modelVersion>4.0.0</modelVersion>
<name>Simple Project</name>
<packaging>jar</packaging>
<version>1.0</version>
<properties>
<spark.version>2.0.1</spark.version>
</properties>
<dependencies>
<dependency> <!-- Spark dependency -->
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.bahir</groupId>
<artifactId>spark-streaming-twitter_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
</dependencies>
</project>
Spark version所有程序包都必须使用相同的主要Spark版本(1.6、2.0、2.1等)。
不正确
name := "Simple Project"
version := "1.0"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % "1.6.1",
"org.apache.spark" % "spark-streaming_2.10" % "2.0.1",
"org.apache.bahir" % "spark-streaming-twitter_2.11" % "2.0.1"
)
我们使用文件可能是spark-core
1.6,而其余组件位于Spark 2.0中。有效
name := "Simple Project"
version := "1.0"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % "2.0.1",
"org.apache.spark" % "spark-streaming_2.10" % "2.0.1",
"org.apache.bahir" % "spark-streaming-twitter_2.11" % "2.0.1"
)
但是最好使用变量
(仍然不正确):
name := "Simple Project"
version := "1.0"
val sparkVersion = "2.0.1"
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.11" % sparkVersion,
"org.apache.spark" % "spark-streaming_2.10" % sparkVersion,
"org.apache.bahir" % "spark-streaming-twitter_2.11" % sparkVersion
)
类似地在Maven:。次版本不匹配并不总是可以接受。
<project> <groupId>com.example</groupId> <artifactId>simple-project</artifactId> <modelVersion>4.0.0</modelVersion> <name>Simple Project</name> <packaging>jar</packaging> <version>1.0</version> <properties> <spark.version>2.0.1</spark.version> <scala.version>2.11</scala.version> </properties> <dependencies> <dependency> <!-- Spark dependency --> <groupId>org.apache.spark</groupId> <artifactId>spark-core_${scala.version}</artifactId> <version>${spark.version}</version> </dependency> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming_${scala.version}</artifactId> <version>${spark.version}</version> </dependency> <dependency> <groupId>org.apache.bahir</groupId> <artifactId>spark-streaming-twitter_${scala.version}</artifactId> <version>${spark.version}</version> </dependency> </dependencies> </project>
- Spark依赖项中使用的Spark版本必须与Spark安装的Spark版本匹配。例如
如果在群集上使用1.6.1,则必须使用1.6.1来构建jars
--jars
的spark-submit
参数-分发本地jar
文件。--packages
的参数[-spark-submit
-从Maven存储库中获取依赖项。jar
中包括应用程序--jars
。在这种情况下,请确保在构建系统中将所有核心Spark依赖项标记为“已提供”,并且如前所述,确保它们与您的运行时Spark版本相关。
application-jar:包含您的应用程序和所有依赖项。该网址必须在您的内部全局可见群集,例如,hdfs://路径或file://路径存在于所有节点上
$PROJECT_ROOT/project/assembly.sbt
的文件addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.0")
added some libraries
libraryDependencies ++ = Seq(“ com.some.company” %%“ some-lib”%“ 1.0.0”)`lazy val root = (project in file(".")).
settings(
name := "spark-samples",
version := "1.0",
scalaVersion := "2.11.12",
mainClass in Compile := Some("StreamingExample")
)
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "2.4.0",
"org.apache.spark" %% "spark-streaming" % "2.4.0",
"org.apache.spark" %% "spark-sql" % "2.4.0",
"com.couchbase.client" %% "spark-connector" % "2.2.0"
)
// META-INF discarding
assemblyMergeStrategy in assembly := {
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case x => MergeStrategy.first
}
我已经使用sbt程序集插件为我的应用创建了一个胖子,但是使用spark-submit运行时失败,并显示以下错误:
java.lang.NoClassDefFoundError: rx/Completable$OnSubscribe
at com.couchbase.spark.connection.CouchbaseConnection.streamClient(CouchbaseConnection.scala:154)
我可以看到该类存在于我的胖子罐中:
jar tf target/scala-2.11/spark-samples-assembly-1.0.jar | grep 'Completable$OnSubscribe'
rx/Completable$OnSubscribe.class
不确定我在这里想念什么,有什么线索吗?
Scala版本
build.sbt
:在这种情况下,请确保在构建系统中将所有核心Spark依赖项标记为“已提供”,并且如前所述,确保它们与您的运行时Spark版本相关。
application-jar
$PROJECT_ROOT/project/assembly.sbt
的文件addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.0")
added some libraries
libraryDependencies ++ = Seq(“ com.some.company” %%“ some-lib”%“ 1.0.0”)`lazy val root = (project in file(".")).
settings(
name := "spark-samples",
version := "1.0",
scalaVersion := "2.11.12",
mainClass in Compile := Some("StreamingExample")
)
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "2.4.0",
"org.apache.spark" %% "spark-streaming" % "2.4.0",
"org.apache.spark" %% "spark-sql" % "2.4.0",
"com.couchbase.client" %% "spark-connector" % "2.2.0"
)
// META-INF discarding
assemblyMergeStrategy in assembly := {
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case x => MergeStrategy.first
}
我已经使用sbt程序集插件为我的应用创建了一个胖子,但是使用spark-submit运行时失败,并显示以下错误:
java.lang.NoClassDefFoundError: rx/Completable$OnSubscribe
at com.couchbase.spark.connection.CouchbaseConnection.streamClient(CouchbaseConnection.scala:154)
我可以看到该类存在于我的胖子罐中:
lazy val root = (project in file(".")).
settings(
name := "spark-samples",
version := "1.0",
scalaVersion := "2.11.12",
mainClass in Compile := Some("StreamingExample")
)
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "2.4.0",
"org.apache.spark" %% "spark-streaming" % "2.4.0",
"org.apache.spark" %% "spark-sql" % "2.4.0",
"com.couchbase.client" %% "spark-connector" % "2.2.0"
)
// META-INF discarding
assemblyMergeStrategy in assembly := {
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case x => MergeStrategy.first
}