gpt4 book ai didi

java - 在同一程序中处理 2 个版本的 hadoop 时,Hadoop jar 冲突问题

转载 作者:可可西里 更新时间:2023-11-01 16:14:55 25 4
gpt4 key购买 nike

以下是我们目前遇到的 Hadoop 不兼容问题。

用例

我们正在从在新 Hadoop(版本 2.2.0.2.0.6.0-101 [Hortonworks])上运行的 HBASE(版本 0.96.1.2.0.6.1-101-hadoop2)读取/扫描并写入旧 Hadoop(版本0.20.2+320 [Cloudera]) 使用 JAVA 程序。但是,由于 2 个 Hadoop 版本之间的不兼容,我们遇到了异常。

下面的代码片段抛出一个异常:

private HbaseConfigFactory(String clusterUri, String hbaseRootdir) throws Exception {
factoryImpl = HBaseConfiguration.create();
factoryImpl.clear();

factoryImpl.set("hbase.zookeeper.quorum", clusterUri);
factoryImpl.set("zookeeper.znode.parent", hbaseRootdir);

// set the zookeeper port
String[] eles = clusterUri.split(":");
if (eles.length > 1) {
factoryImpl.set("hbase.zookeeper.property.clientPort", eles[1]);
}

try {
//THE BELOW CODE CAUSE THE EXCEPTION
HBaseAdmin.checkHBaseAvailable(factoryImpl);

} catch (Exception e) {
String message = String.format("HBase is currently unavailable: %s, %s",
e.getMessage(), e);
logger.error(message);

throw new Exception(e);
}

}

波纹管是个异常(exception):

java.lang.Exception:java.lang.IllegalArgumentException:在 org.apache.hadoop.security.UserGroupInformation 中找不到方法 getCurrentUser! 在 com.shopping.writetold.HbaseConfigFactory.(HbaseConfigFactory.java:36) 在 com.shopping.writetold.HbaseConfigFactory.getInstance(HbaseConfigFactory.java:48) 在 com.shopping.writetold.WriteToHDFS.readDeals(WriteToHDFS.java:63) 在 com.shopping.writetold.WriteToHDFS.main(WriteToHDFS.java:50) 在 sun.reflect.NativeMethodAccessorImpl.invoke0( native 方法) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:601) 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)原因:java.lang.IllegalArgumentException:在 org.apache.hadoop.security.UserGroupInformation 中找不到方法 getCurrentUser! 在 org.apache.hadoop.hbase.util.Methods.call(Methods.java:45) 在 org.apache.hadoop.hbase.security.User.call(User.java:414) 在 org.apache.hadoop.hbase.security.User.callStatic(User.java:404) 在 org.apache.hadoop.hbase.security.User.access$200(User.java:48) 在 org.apache.hadoop.hbase.security.User$SecureHadoopUser.(User.java:221) 在 org.apache.hadoop.hbase.security.User$SecureHadoopUser.(User.java:216) 在 org.apache.hadoop.hbase.security.User.getCurrent(User.java:139) 在 org.apache.hadoop.hbase.client.HConnectionKey.(HConnectionKey.java:67) 在 org.apache.hadoop.hbase.client.HConnectionManager.getConnection(HConnectionManager.java:240) 在 org.apache.hadoop.hbase.client.HBaseAdmin.checkHBaseAvailable(HBaseAdmin.java:2321) 在 com.shopping.writetold.HbaseConfigFactory.(HbaseConfigFactory.java:29) ... 还有 8 个引起:java.lang.NoSuchMethodException:org.apache.hadoop.security.UserGroupInformation.getCurrentUser() 在 java.lang.Class.getMethod(Class.java:1624) 在 org.apache.hadoop.hbase.util.Methods.call(Methods.java:38) ... 还有 18 个

Maven 依赖项:

  <dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-core</artifactId>
<version>0.20.2</version>
</dependency>

<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>0.96.0-hadoop2</version>
</dependency>

jar 细节Maven:org.apache.hadoop:hadoop-common:2.1.0-betahadoop-common-2.1.0-beta.jar

类文件 UserGroupInformation 中的方法签名公共(public)静态同步 org.apache.hadoop.security.UserGroupInformation getCurrentUser() 抛出 java.io.IOException

jar 细节Maven:org.apache.hadoop:hadoop-core:0.20.2hadoop-core-0.20.2.jar

类文件 UserGroupInformation 中的方法签名静态 javax.security.auth.Subject getCurrentUser()

两者具有相同的 namespace ,即:包 org.apache.hadoop.security;

当我有单独的程序从 hbase 读取并仅使用各自的 jar 写入 cloudera HDFS 时,它们工作正常。

在单个程序中有没有解决上述不兼容问题的方案。

谢谢萨加尔B

最佳答案

免责声明:作为先决条件,我认为更新到最新的统一 Hadoop 库是不可能的,但我对 Hadoop 几乎一无所知。

本质上,您处于冲突中,因为您将在运行时同时需要类路径中的两个库,这是一项艰巨的任务。为了在同一个虚拟机中拥有两个来自不同来源的相同类,您将需要使用至少两个不同的类加载器。

从技术/架构的角度来看,在这种情况下要做的事情是将应用程序的两个部分解耦。要么在同一 VM 中使用不同的类加载器运行,要么实际上将其解耦为使用共享机制交换消息的异构程序(想到 jms,但还有很多替代方案)。

由于您想要探索单个 VM 问题,因此您面临两个选择。手动执行或使用支持此 (OSGI) 的应用程序容器。无论哪种情况,您都需要至少在 maven 中解耦应用程序以区分它们的依赖关系等。

手动意味着将应用程序的一部分放在当前类加载器中,然后从自定义类加载器加载第二部分,因此假设写入部分卸载到单独的 jar 中,创建一个加载旧 Hadoop 的自定义类加载器jar(和适用的传递)和这个单独的 jar 文件。相当技术性,但可行..

我找到了一个使用 java.util.ServiceLoader 的引用问题,它可能会突出主题,使用后果自负。 ( Dynamically loading plugin jars using ServiceLoader )

另一个真正适用于这个原因的解耦解决方案是 OSGI 模型,它允许 jar 在 pier-hierarchy 中有自己独立的运行时依赖树,这实质上意味着同一个类可能存在于 vm 的多个版本中,因为它是每个 jar 的一个类加载器。但是,由于许多其他原因,OSGI 是另一种野兽,需要付出一定程度的艰苦学习努力才能真正理解和利用。

关于java - 在同一程序中处理 2 个版本的 hadoop 时,Hadoop jar 冲突问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23530948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com