IncompatibleClassChangeError when 运行 spark from (spring) servlet

IncompatibleClassChangeError when running spark from (spring) servlet

当 运行 来自 (spring) 网络应用程序的简单 spark 作业时,我得到一个 IncompatibleClassChangeError。这可能是由于一些不兼容的依赖项,但我找不到哪个。

简单来说,this is the issue有异常堆栈。

这里是the failing code:

// file conversion with spark
// --------------------------
JavaRDD<String> inputRdd = sparkContext.textFile(inputFile).cache();

Function fct = new Function<String,String>() {
    @Override
    public String call(String line) throws Exception {
        return line.toUpperCase();
    }
};
JavaRDD<Strineg> outputRdd = inputRdd.map(fct); // *** fail ***

outputRdd.saveAsTextFile(outputDir);

它是从 a simple spring servlet:

调用的
@RequestMapping(method = RequestMethod.GET, value="/upper")
public @ResponseBody boolean upper(@RequestParam(required = true) String inputFile,
                                   @RequestParam(required = true) String outputDir,
                                   @RequestParam(required = false) String master,
                                   @RequestParam(required = false) String namenode) {
    if(master==null) master = "local";
    SparkUpper.upper(inputFile, outputDir, master, namenode);

    return true;
}

这里是 the (maven) dependencies:

<dependencies>
  <!-- spring -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <!-- spark & hadoop -->
  <dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-core_2.10</artifactId>
    <version>1.2.1</version>
  </dependency>
  <dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-core</artifactId>
    <version>1.2.1</version>
  </dependency>
  <dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>2.5.2</version>
  </dependency>

</dependencies>

奇怪的是,基本上做同样的事情,具有相同的 spark 依赖关系,但从 servlet 调用,如 this project 中那样工作正常。

任何想法将不胜感激。

在尝试使用 mvn dependency:tree -Dverbose 来调查依赖冲突后发现了太多依赖冲突,我找到了一个实用的解决方案:

将 war 中包含的 Maven 依赖项替换为我曾经 运行 我的 previous non-spring code.

spark-assembly-1.1.1-hadoop2.4.0.jar

实践中:

  1. 在本地 maven 中安装 spark-assembly jar:

    mvn install:install-file \ -Dfile=$SPARK_HOME/lib/spark-assembly-1.1.1-hadoop2.4.0.jar \ -DgroupId=org.apache.spark -DartifactId=spark-assembly-jar \ -Dversion=1.1.1 -Dpackaging=jar

  2. 将其包含在 Maven 依赖项中:

    <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-assembly-jar</artifactId> <version>1.1.1</version> </dependency>

  3. 通过将 <scope>provided</scope> 添加到 spark-corehadoop-corehadoop-client,从 war 中删除 spark 和 hadoop jar。 =20=]

据我了解,冲突可能发生在 spark 和 hadoop 依赖项之间,而不是来自 spark/hadoop vs spring。但这可以通过使用包含一起构建的所有内容的 spark-assembly jar 来绕过。

这不是一个非常令人满意的解决方案,它添加了 140MB 的 jar 依赖项,但它确实有效。最好找到一组合适的 spark/hadoop 实际相互配合的依赖项。

此外,我可以寻找一种方法将此 spark-assembly jar 包含在 servlet 容器的类路径中,而不是包含在 war.