有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

httpclient版本与Apache Spark之间的java冲突

我正在使用ApacheSpark开发一个Java应用程序。我使用这个版本:

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-core_2.10</artifactId>
    <version>1.2.2</version>
</dependency>

在我的代码中,有一个过渡依赖项:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>

我将应用程序打包到一个JAR文件中。当使用spark-submit在EC2实例上部署它时,我得到了这个错误

Caused by: java.lang.NoSuchFieldError: INSTANCE
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.<clinit>(SSLConnectionSocketFactory.java:144)
    at com.amazonaws.http.apache.client.impl.ApacheConnectionManagerFactory.getPreferredSocketFactory(ApacheConnectionManagerFactory.java:87)
    at com.amazonaws.http.apache.client.impl.ApacheConnectionManagerFactory.create(ApacheConnectionManagerFactory.java:65)
    at com.amazonaws.http.apache.client.impl.ApacheConnectionManagerFactory.create(ApacheConnectionManagerFactory.java:58)
    at com.amazonaws.http.apache.client.impl.ApacheHttpClientFactory.create(ApacheHttpClientFactory.java:50)
    at com.amazonaws.http.apache.client.impl.ApacheHttpClientFactory.create(ApacheHttpClientFactory.java:38)

此错误清楚地表明SparkSubmit已加载同一Apache httpclient库的较旧版本,因此发生此冲突

解决这个问题的好办法是什么

由于某些原因,我无法在Java代码上升级Spark。然而,我可以用EC2集群轻松做到这一点。是否可以在更高版本(如1.6.1版本)的集群上部署java代码


共 (1) 个答案

  1. # 1 楼答案

    正如您在帖子中所说,Spark正在加载httpclient的旧版本。解决方案是使用Maven的^{}工具生成一个整洁的无冲突项目

    下面是一个如何在pom.xml文件中使用它的示例:

    <project>
      <!  Your project definition here, with the groupId, artifactId, and it's dependencies  > 
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>shade</goal>
                </goals>
                <configuration>
                  <relocations>
                    <relocation>
                      <pattern>org.apache.http.client</pattern>
                      <shadedPattern>shaded.org.apache.http.client</shadedPattern>
                    </relocation>
                  </relocations>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    
    </project>
    

    这将把所有文件从org.apache.http.client移动到shaded.org.apache.http.client,从而解决冲突


    原创帖子:

    如果这只是一个可传递依赖项的问题,您可以将其添加到spark-core依赖项中,以排除Spark使用的HttpClient:

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_2.10</artifactId>
        <version>1.2.2</version>
        <scope>provided</scope>
        <exclusions>
            <exclusion>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    

    我还在依赖项中添加了scope作为provided,因为它将由集群提供

    然而,这可能会影响Spark的内部行为。如果执行此操作后仍然出现错误,可以尝试使用Maven的^{}工具,该工具将生成一个整洁的无冲突项目

    关于不能升级Spark的版本这一事实,您是否使用了来自mvnrepository的this dependency声明

    Spark向后兼容,在更高版本的集群上部署作业应该不会有任何问题