Apache Spark - 使用spark-submit抛出NoSuchMethodError

6 java nosuchmethoderror guava maven-shade-plugin spark-submit

要将Spark应用程序提交到集群,他们的文档说明:

为此,请创建包含代码及其依赖项的程序集jar(或"uber"jar).sbt和Maven都有汇编插件.在创建程序集jar时,将Spark和Hadoop列为提供的依赖项; 这些不需要捆绑,因为它们是由集群管理器在运行时提供的.- http://spark.apache.org/docs/latest/submitting-applications.html

所以,我在我的pom.xml文件中添加了Apache Maven Shade插件.(版本3.0.0)
我将Spark依赖项的范围转换为provided.(版本2.1.0)

(我还添加了Apache Maven Assembly Plugin,以确保我在运行时将所有依赖项都包装在jar中mvn clean package.我不确定它是否真的有必要.)


这样就spark-submit失败了.它抛出一个NoSuchMethodError依赖我的(请注意,代码在IntelliJ内部编译时从本地实例工作,假设provided已删除).

Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Stopwatch.createStarted()Lcom/google/common/base/Stopwatch;
Run Code Online (Sandbox Code Playgroud)

抛出错误的代码行是无关紧要的 - 它只是我的main方法中创建Stopwatch一部分Google Guava实用程序的第一行.(版本21.0)

在线的其他解决方案表明它与Guava的版本冲突有关,但我对这些建议还没有任何运气.任何帮助将不胜感激,谢谢.

sum*_*tsu 5

如果查看/jarsSpark 2.1.0安装的子目录,则可能会看到guava-14.0.1.jar。根据您正在使用的Guava Stopwatch#createStarted方法API,createStarted直到Guava 15.0才存在。最有可能发生的事情是,Spark进程Classloader在找到打包在uberjar中的Guava 21.0库之前,先找到了Spark提供的Guava 14.0.1库。

一种可能的解决方法是使用Maven Shade插件提供类重定位功能(您已经在使用它来构建uberjar)。通过“类重定位”,Maven-Shade在打包uberjar的过程中将Guava 21.0类(您的代码需要)从pattern反映其现有包名称的位置(例如com.google.common.base)移动到shadedPattern您在Shade配置中指定的任意位置(例如myguava123.com.google.common.base)。

结果是较新的Guava库不再共享包名,从而避免了运行时冲突。