java - 解决Apache Spark中的依赖性问题

标签 java scala apache-spark classnotfoundexception nosuchmethoderror

构建和部署Spark应用程序时的常见问题是:
java.lang.ClassNotFoundException
object x is not a member of package y编译错误。
java.lang.NoSuchMethodError
如何解决这些问题?

最佳答案

apache spark的类路径是动态构建的(以适应每个应用程序的用户代码),这使得它容易受到此类问题的攻击。@user7337271的答案是正确的,但还有一些问题,这取决于您使用的集群管理器(“master”)。
首先,spark应用程序由这些组件组成(每个组件都是单独的jvm,因此可能在其类路径中包含不同的类):
驱动程序:这是您的应用程序创建SparkSession(或SparkContext)并连接到群集管理器以执行实际工作
集群管理器:作为集群的“入口点”,负责为每个应用程序分配执行器。Spark支持几种不同的类型:独立型、纱线型和介观型,我们将在下面介绍这些类型。
执行器:这些是集群节点上的进程,执行实际的工作(运行spark任务)
ApacheSpark的cluster mode overview中的图表描述了它们之间的关系:
Cluster Mode Overview
现在-哪些类应该位于这些组件中的每个组件中?
这可以用下图来回答:
Class placement overview
让我们慢慢分析一下:
spark代码是spark的库。它们应该存在于所有三个组件中,因为它们包括了让火花执行它们之间通信的胶水。顺便说一下,Spark的作者做出了一个设计决定,在所有组件中包含所有组件的代码(例如,在驱动程序中也包含应该只在Executor中运行的代码),以简化这一点,因此Spark的“胖罐子”(在1.6版本中)或“存档”(在2.0版本中,详细信息如下)包含了必要的代码所有组件的de都应可用。
仅驱动程序代码这是用户代码,不包括任何应该在执行器上使用的代码,即在rdd/dataframe/dataset上的任何转换中都不使用的代码。这不一定要从分布式用户代码中分离出来,但也可以。
分布式代码这是用驱动程序代码编译的用户代码,但也必须在执行器上执行-实际转换使用的所有内容都必须包含在这个jar中。
既然我们已经明白了,我们如何让类在每个组件中正确加载,它们应该遵循什么规则?
spark代码:正如前面的应答状态一样,您必须在所有组件中使用相同的scala和spark版本。
1.1在独立模式下,有一个“预先存在的”Spark安装,应用程序(驱动程序)可以连接到该安装。这意味着所有的驱动程序都必须使用主程序和执行程序上运行的相同的spark版本。
1.2在纱线/介子中,每个应用程序可以使用不同的火花版本,但同一应用程序的所有组件必须使用同一个。这意味着,如果使用x版编译和打包驱动程序应用程序,则在启动sparksession时应提供相同的版本(例如,使用yarn时通过spark.yarn.archivespark.yarn.jars参数)。您提供的jars/archive应该包含所有spark依赖项(包括可传递依赖项),当应用程序启动时,集群管理器会将其发送给每个执行器。
驱动程序代码:这完全取决于驱动程序代码可以作为一堆jar或“胖jar”来发布,只要它包含所有spark依赖项+所有用户代码
分布式代码:除了存在于驱动程序中之外,此代码还必须发送到执行器(同样,连同其所有可传递依赖项)。这是使用spark.jars参数完成的。
总而言之,这里有一个构建和部署spark应用程序的建议方法(在本例中是使用yarn):
使用您的分布式代码创建一个库,将其打包为一个“常规”jar(用一个.pom文件描述其依赖项)和一个“胖jar”(包括其所有可传递的依赖项)。
创建一个驱动程序应用程序,其编译依赖于您的分布式代码库和apache spark(具有特定版本)
将驱动程序应用程序打包到一个fat jar中以部署到驱动程序
启动spark.jars时,将正确版本的分布式代码作为SparkSession参数的值传递
将包含下载的spark二进制文件的lib/文件夹下所有jar的存档文件(例如gzip)的位置传递为spark.yarn.archive

关于java - 解决Apache Spark中的依赖性问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54515863/

相关文章:

apache-spark - Spark 流: using object as key in 'mapToPair'

java - Android 测试不会在低于 5 (API 21) 的设备上运行 NoClassDefFoundError

scala - Spark : way to join each row of dataframe with all rows of another dataframe

scala - 使用 FileStream 读取文件,会阻塞吗?

scala - 为什么 paramGridBuilder 与 CountVectorizer 发生 scala 错误?

java - 如何在 Java 中使用 Flatmap 和个性化对象

hadoop - Apache Spark 是同时读取和处理,还是先读取内存中的整个文件然后开始转换?

java - 启动 Datomic shell 时出错 : java. lang.NoClassDefFoundError: jline/ConsoleRunner

java - 无法在独立的 java 应用程序上运行 PJSIP-JNI 包装器

java - 无法在 apache-camel 中创建路由