【问题标题】:Conflict between httpclient version and Apache Sparkhttpclient 版本与 Apache Spark 冲突
【发布时间】:2016-10-17 00:55:48
【问题描述】:

我正在使用 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 版本?

【问题讨论】:

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


    【解决方案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 版本的事实,您是否使用了来自 mvnrepository 的 this dependency 声明?

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

    【讨论】:

    • 问题确实通过搬迁解决了。如果您详细说明如何使用apache-shade-plugin,我将接受它作为答案。
    • @M-T-A 很高兴它有帮助。我更新了我的答案,但是你能确认我在模式标签中引用了正确的包吗?
    • 注意,您可能还需要将模式设置为以下以解决 http.conn 的问题。:org.apache.http.shaded。 org.apache.http.
    • 非常感谢,这真的很有帮助!我正在添加一个指向另一个问题的链接,该链接解释了如何relocate via SBT,因为这可能会有所帮助,就像对我一样。
    猜你喜欢
    • 2019-06-21
    • 2018-05-14
    • 2017-05-16
    • 1970-01-01
    • 2020-03-10
    • 2018-01-24
    • 1970-01-01
    • 2020-03-27
    • 1970-01-01
    相关资源
    最近更新 更多