根据业务需求,需要在数据源管理中,针对Hive数据源类型增加对iceberg能力的支持。目前将分享下在java程序中使用iceberg的HiveCatalog时遇到的问题及解决方法。
底座环境:
Hive版本:3.1.2
iceberg-hive-runtime:1.1.0
翼MR Manage:2.12.10
程序依赖:
<dependency>
<groupId>org.apache.iceberg</groupId>
<artifactId>iceberg-core</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.apache.iceberg</groupId>
<artifactId>iceberg-hive-metastore</artifactId>
<version>1.4.3</version>
</dependency>
背景:
目前各类数据源是以jar包方式打包个独立的插件,通过自定义类加载器进行插件资源加载。
HiveCatalog的创建方式:
Map<String, String> properties = new HashMap<>(2);
properties.put(CatalogProperties.CATALOG_IMPL, HiveCatalog.class.getName());
HiveConf hiveConf = new HiveConf(PluginHiveClientPool.class);
hiveConf.addResource(new Path(hiveSitePath));
hiveConf.addResource(new Path(coreSitePath));
hiveConf.addResource(new Path(hdfsSitePath));
HiveCatalog hiveCatalog = ugi.doAs((PrivilegedExceptionAction<HiveCatalog>) () -> {
HiveCatalog ugiHiveCatalog = new HiveCatalog();
hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_KERBEROS_PRINCIPAL, principal);
hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_KERBEROS_KEYTAB, keytabPath);
hiveConf.setVar(HiveConf.ConfVars.METASTORE_KERBEROS_KEYTAB_FILE, keytabPath);
ugiHiveCatalog.setConf(hiveConf);
ugiHiveCatalog.initialize("hive", properties);
return ugiHiveCatalog;
});
问题阐述:
当创建完HiveCatalog之后,调用方法listNamespaces去尝试HiveCatalog是否真正的创建成功并可用正常调用iceberg时,出现异常:
但再次重新创建HiveCatalog并调用listNamespaces时,异常却又没有再次出现。
根据异常信息,查看到iceberg-hivemetastore的源码,找到以下代码:
其中GET_CLIENT对象是:
使用的是动态代理的方式进行调用,再继续往下找,
此处就是抛出异常的地方。
但如果直接参考JavaUtils的方法,获取HiveMetaStoreClient,是可以正常获取的,因此并非是自定义类加载器的原因。
尝试更换程序的iceberg相关依赖的版本,也依旧出现此异常。
目前解决方法如下:
重写HiveCatalogPool.java的newClient方法,不走动态代理的方式,直接通过new HiveMetaStoreClient(conf)的方式进行创建。
目前暂未发现有HiveMetaStoreClient类不存在的异常。