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

标签 java apache-spark amazon-ec2 apache-httpclient-4.x

我正在使用 Apache Spark 开发 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 集群轻松做到这一点。是否可以将我的 java 代码部署到具有更高版本(例如 1.6.1 版本)的集群上?

最佳答案

正如您在帖子中所说,Spark 正在加载旧版本的 httpclient。解决方案是使用 Maven 的 relocation设施来产生一个整洁的无冲突项目。

这是一个如何在您的 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 的 relocation应产生整洁无冲突项目的设施。

关于你不能升级Spark的版本,你使用的是this dependency吗?来自 mvnrepository 的声明?

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

关于java - httpclient 版本与 Apache Spark 之间的冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37843400/

相关文章:

reactjs - 如何使用基于路径的路由负载均衡器为部署在 AWS ECS 上的 React.js 应用程序设置 nginx 配置

amazon-ec2 - EC2 yum 更新失败

java - 在默认接口(interface)方法中使用对象的类型参数

java 如何创建通用单例类

scala - 如何使用复杂的嵌套结构修改Spark Dataframe?

apache-spark - Spark 2.3 java.lang.NoSuchMethodError : io.netty.buffer.PooledByteBufAllocator.metric

JAVA - 在 30 个字符后的下一个空格处插入一个新行

java - 如何使用vert.x配置读取json文件?

java - 无法执行多个 Spark 作业 "Initial job has not accepted any resources"

spring-boot - 如何从 GitLab 存储库将 Web 应用程序部署到 AWS 实例