【问题标题】:Apache Spark -- using spark-submit throws a NoSuchMethodErrorApache Spark——使用 spark-submit 抛出 NoSuchMethodError
【发布时间】:2017-07-12 22:18:00
【问题描述】:

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

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

所以,我将 Apache Maven Shade 插件添加到我的 pom.xml 文件中。 (版本 3.0.0)
我把我的 Spark 依赖的范围变成了provided。 (2.1.0 版)

(我还添加了 Apache Maven 程序集插件,以确保在运行 mvn clean package 时将所有依赖项包装在 jar 中。我不确定它是否真的有必要。)


spark-submit 就是这样失败的。它会为我拥有的依赖项抛出 NoSuchMethodError(请注意,在 IntelliJ 中编译时,代码在本地实例中工作,假设已删除 provided)。

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

引发错误的代码行无关紧要——它只是我的 main 方法中创建 Stopwatch 的第一行,它是 Google Guava 实用程序的一部分。 (21.0版)

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

【问题讨论】:

    标签: java guava nosuchmethoderror maven-shade-plugin spark-submit


    【解决方案1】:

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

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

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

    【讨论】:

    • 谢谢,在阴影插件中添加relocation 部分修复了错误。此外,我能够删除程序集插件,它仍然可以正常工作。
    【解决方案2】:

    很可能你遇到了依赖冲突,是的。

    首先,您可以在构建 jar 时查看是否存在依赖项冲突。一种快速的方法是直接查看您的 jar 以查看 Stopwatch.class 文件是否存在,并且通过查看字节码,方法 createStarted 是否存在。 否则,您还可以列出依赖关系树并从那里开始工作:https://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html

    如果这不是您的 jar 的问题,则可能是由于您的 spark 安装和您的 jar 之间的冲突而导致的依赖问题。 查看 spark 安装的 lib 和 jars 文件夹。在那里你可以看到你的 jars 是否包含不支持来自 Stopwatch 的方法 createStarted() 的 guava 的替代版本

    【讨论】:

    • jar 中存在Stopwatch.createStarted() 方法,我现在正在检查 Spark 是否已经有任何冲突的 Guava 版本。
    • 看起来 Spark 2.1.0 的 jars 目录中有 guava-14.0.1.jar
    【解决方案3】:

    通过以下配置应用以上答案来解决问题:

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
                <relocations>
                    <relocation>
                        <pattern>com.google.common</pattern>
                        <shadedPattern>shade.com.google.common</shadedPattern>
                    </relocation>
                    <relocation>
                        <pattern>com.google.thirdparty.publicsuffix</pattern>
                        <shadedPattern>shade.com.google.thirdparty.publicsuffix</shadedPattern>
                    </relocation>
              </relocations>
            </configuration>
          </execution>
        </executions>
      </plugin>
    

    【讨论】:

      猜你喜欢
      • 2017-11-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      • 1970-01-01
      相关资源
      最近更新 更多