7

要将 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 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;

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

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

4

3 回答 3

5

如果您查看/jarsSpark 2.1.0 安装的子目录,您可能会看到guava-14.0.1.jar. 根据您正在使用的 Guava方法的API,Stopwatch#createStartedcreateStarted直到 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)的位置移动到您在 Shade 配置中指定的任意shadedPattern位置(例如myguava123.com.google.common.base)。

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

于 2017-02-22T19:02:02.550 回答
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 文件夹。在那里您可以查看是否有包含不支持来自 Stopwatch 的方法 createStarted() 的替代版本的番石榴的 jar

于 2017-02-22T18:39:08.930 回答
1

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

  <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-12-28T06:57:33.890 回答