从(spring)servlet运行spark时出现IncompatibleClassChangeError

时间:2015-03-04 16:54:48

标签: spring servlets apache-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中工作正常一样。

任何想法都将不胜感激。

1 个答案:

答案 0 :(得分:0)

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

用我用来运行previous non-spring codespark-assembly-1.1.1-hadoop2.4.0.jar替换战争中包含的maven依赖项。

在实践中:

  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,从战争中移除火花和hadoop jar。

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

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

    另外,我可以寻找一种方法将这个spark-assembly jar包含在servlet容器的类路径中而不是战争中。