httpclient 版本与 Apache Spark 之间的冲突
Conflict between httpclient version and Apache Spark
我正在使用 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 版本?
正如您在 post 中所说,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
,从而解决冲突。
原文post:
如果这只是传递依赖关系的问题,您可以将它添加到您的 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 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 版本?
正如您在 post 中所说,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
,从而解决冲突。
原文post:
如果这只是传递依赖关系的问题,您可以将它添加到您的 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 向后兼容,在更高版本的集群上部署作业应该没有任何问题。