EMR5.35上Spark Java程序调用HBaseConfiguration.create()崩溃
问题背景
在EMR 5.35集群(配套组件版本:Hadoop 2.10、Spark 2.4.8、HBase 1.4.13)上运行Java编写的Spark程序,未加入HBase连接逻辑时程序运行正常;加入HBase相关代码后,程序在配置创建阶段直接终止。
经排查,注释掉HBaseConfiguration.create()后的所有代码,程序依然崩溃,确认问题出在HBaseConfiguration.create()这行调用。运行时无有效错误堆栈输出,Driver进程执行到该行时立即终止。
问题相关代码片段:
conf = HBaseConfiguration.create(); for (Iterator<Map.Entry<String, String>> it = conf.iterator(); it.hasNext(); ) { Map.Entry<String, String> e = it.next(); System.out.println(e); } connection = ConnectionFactory.createConnection(conf); admin = connection.getAdmin();
已尝试的无效方案:手动加载集群配置文件,代码如下,未解决问题:
conf = HBaseConfiguration.create(); conf.addResource(new Path("/etc/hadoop/conf/core-site.xml")); conf.addResource(new Path("/etc/hbase/conf/hbase-site.xml"));
项目POM配置
<properties> <spark.version>2.4.8</spark.version> <hbase.version>1.4.13</hbase.version> <hadoop.version>2.10.1</hadoop.version> <jackson.version>2.13.2</jackson.version> <java.build.version>1.8</java.build.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.17.103</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.77.Final</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty</artifactId> <version>3.9.9.Final</version> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.12</artifactId> <version>${spark.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.12</artifactId> <version>${spark.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-aws</artifactId> <version>${hadoop.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>${hadoop.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-client</artifactId> <version>${hbase.version}</version> <scope>provided</scope> </dependency> <!-- AWS依赖 --> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>athena</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>auth</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>opensearch</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.15</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>5.6.16</version> </dependency> </dependencies>
问题根因
该问题属于典型的依赖版本不匹配触发的JVM类加载致命错误,这类错误发生在类静态初始化阶段时,经常会出现进程直接退出、无有效错误堆栈的现象,核心不匹配点有3个:
- EMR 5.35配套的Spark 2.4.8基于Scala 2.11编译,POM中引用的Spark依赖为
_2.12后缀的Scala 2.12版本,Scala大版本不兼容会导致类加载时触发二进制不兼容错误。 - POM中在
dependencyManagement节点强制指定了Netty版本,和集群内置的HBase、Hadoop、Spark自带的Netty版本不一致,触发NoSuchMethodError类链接错误。 - POM中自定义的Hadoop版本为2.10.1、Jackson版本为2.13.2,和EMR集群内置的Hadoop 2.10、Spark 2.4.x内置的Jackson 2.9.x版本不匹配,进一步加剧类冲突问题。
修复步骤
- 修正Spark依赖的Scala版本:将所有Spark依赖的artifactId后缀从
_2.12改为_2.11,和集群Spark的Scala编译版本完全对齐。 - 删除
dependencyManagement节点下两个Netty相关的版本强制声明,不得手动覆盖集群内置的Netty版本,避免触发类方法找不到的链接错误。 - 对齐集群组件版本:将
hadoop.version调整为和集群一致的2.10.0,删除自定义的jackson.version配置,直接使用集群内置的Jackson版本。 - 提交任务时显式指定HBase依赖路径:使用
spark-submit提交任务时,追加以下两个配置即可,无需在代码中手动调用addResource加载配置文件,HBaseConfiguration会自动读取classpath下的配置:
--conf spark.driver.extraClassPath=/etc/hbase/conf:/usr/lib/hbase/lib/* --conf spark.executor.extraClassPath=/etc/hbase/conf:/usr/lib/hbase/lib/*
内容的提问来源于stack exchange,提问作者bocacorazon
相关产品推荐
相关产品推荐

