背景:
某大型国企总部要抽取地方公司的数据,总部和地方都是用的华为的数据中台。需要我们自己开发一个API接口,总部通过调用API接口抽取地方中台的数据。
存在的问题:
开发环境:
首先是开发环境的问题,因为总部和地方部署华为中台都是私有云,我没有私有云的环境,因此我是自己申请的公有云环境开发的。
另外需要注意华为MRS的hive为高可用,连接一律是需要通过zookeeper。
(1)网络问题:
申请华为公有云的MRS后一定要配置集群所在服务器ECS绑定公网IP。
(2)安全组问题(适用生产环境私有云):
修改绑定MRS的安全组,添加本机电脑或者服务器(或0.0.0.0任意IP)的2181、10000等端口的准入。
(3)配置公网IP与ECS服务器的别名(适用生产环境私有云):
因为是通过zookeeper连接hive,程序自动从zookeeper中拿到的其实是hive集群所在服务器的别名,因此需要对应公网IP与ECS服务器的别名。
生产环境:
生产环境中hive集群集成了kerberos安全认证,程序中需要添加安全认证代码。
(1)添加安全认证:
Kerberos安全认证示例代码如下:
System.setProperty("java.security.krb5.conf","/var/cqljgt_springboot/conf/krb5.conf");
org.apache.hadoop.conf.Configuration conf = new org.apache.hadoop.conf.Configuration();
if (isSecurityMode) {
String userName = "cq_xxxx_xxxx";
String userKeytabFile = "/var/cqljgt_springboot/conf/user.keytab";
String krb5File = "/var/cqljgt_springboot/conf/krb5.conf";
conf.set(HADOOP_SECURITY_AUTHENTICATION, "Kerberos");
conf.set(HADOOP_SECURITY_AUTHORIZATION, "true");
conf.addResource(new FileInputStream(new File("/var/cqljgt_springboot/conf/core-site.xml")));
conf.addResource(new FileInputStream(new File("/var/cqljgt_springboot/conf/hivemetastore-site.xml")));
conf.addResource(new FileInputStream(new File("/var/cqljgt_springboot/conf/hive-site.xml")));
LoginUtil.setJaasConf("Client", userName, userKeytabFile);
LoginUtil.setZookeeperServerPrincipal("zookeeper/hadoop");
LoginUtil.login(userName, userKeytabFile, krb5File, conf);
}
其中LoginUtil来自华为官网示例代码:
https://github.com/huaweicloud/huaweicloud-mrs-example/blob/mrs-2.1/src/hive-examples/src/main/java/com/huawei/bigdata/security/LoginUtil.java
下面就是巨坑,这两行代码中的Client和zookeeper/hadoop千万不要改动:
LoginUtil.setJaasConf("Client", userName, userKeytabFile);
LoginUtil.setZookeeperServerPrincipal("zookeeper/hadoop");
正常就是这样的:
如果上面的两行代码有改动,则根据zookeeper拿不到hive的地址:
上面是我的代码中的日志,其他人的可能不是这样,但应该是报这个错误的:
Exception in thread "main" java.sql.SQLException: org.apache.hive.jdbc.ZooKeeperHiveClientException: Unable to read HiveServer2 configs from ZooKeeper
at org.apache.hive.jdbc.HiveConnection.<init>(HiveConnection.java:144)
at org.apache.hive.jdbc.HiveDriver.connect(HiveDriver.java:105)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
at JDBCExample.main(JDBCExample.java:82)
Caused by: org.apache.hive.jdbc.ZooKeeperHiveClientException: Unable to read HiveServer2 configs from ZooKeeper
at org.apache.hive.jdbc.ZooKeeperHiveClientHelper.configureConnParams(ZooKeeperHiveClientHelper.java:100)
at org.apache.hive.jdbc.Utils.configureConnParams(Utils.java:509)
at org.apache.hive.jdbc.Utils.parseURL(Utils.java:429)
at org.apache.hive.jdbc.HiveConnection.<init>(HiveConnection.java:142)
... 4 more
Caused by: org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /hiveserver2
at org.apache.zookeeper.KeeperException.create(KeeperException.java:99)
at org.apache.zookeeper.KeeperException.create(KeeperException.java:51)
at org.apache.zookeeper.ZooKeeper.getChildren(ZooKeeper.java:2374)
at org.apache.curator.framework.imps.GetChildrenBuilderImpl$3.call(GetChildrenBuilderImpl.java:214)
at org.apache.curator.framework.imps.GetChildrenBuilderImpl$3.call(GetChildrenBuilderImpl.java:203)
at org.apache.curator.RetryLo,op.callWithRetry(RetryLoop.java:107)
at org.apache.curator.framework.imps.GetChildrenBuilderImpl.pathInForeground(GetChildrenBuilderImpl.java:200)
at org.apache.curator.framework.imps.GetChildrenBuilderImpl.forPath(GetChildrenBuilderImpl.java:191)
at org.apache.curator.framework.imps.GetChildrenBuilderImpl.forPath(GetChildrenBuilderImpl.java:38)
上面报错的原因也很大可能是“Client”和“zookeeper/hadoop”这儿的问题,如果确信不是这个原因,也可以查看一下的华为官网解决方案:
https://support.huaweicloud.com/trouble-mrs/mrs_03_0172.html
至于为什么“Client”和“zookeeper/hadoop”不能改动,我在官网没有查到。“zookeeper/hadoop”则是涉及到zookeeper安全认证的principal,或许这就是默认的吧。
(2)账号权限问题:
下面就是第二个巨坑了。kerberos通过之后,代码中运行jdbc查询表,报错:
org.apache.hive.service.cli.HiveSQLException: Error while compiling statement: FAILED: HiveAccessControlException Permission denied: Principal [name=cq_xxxx_xxxx, type=USER] does not have following privileges for operation DESCTABLE [[SELECT] on Object [type=TABLE_OR_VIEW, name=dwd_pms.t_zh_ztjx_sysjz]]
大致的意思就是给我们的hive账户没有查询表的权限。
中台工作人员给的答复是,每次执行SQL语句前都要加上set role admin,他那边儿一切没问题,有问题是你代码的问题,他还给了验证:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201127110722838.png?x-oss-process=image/watermark,type_ZmFuZ3poZW
什么?难道不是超级管理员给赋权嘛,自己给自己赋权。然后我怀着怀疑的态度照他们的建议在代码中添加set role admin后又去执行的代码,果然还是有问题的。错误提示用户不属于admin角色:
然后我在华为官网查到了解决方法(这难道就是一切没问题嘛):
(3)用户、角色等的修改后,kerberos认证文件需要重新下载
中台的人对hive账号的权限做出修改后,就突然的kerberos安全认证通过不了了。为此又花了一天的时间排查这个问题,最后我好像在华为官网找到了答案:
成果:
所有问题得到解决后:
总结:
本来一天时间就开发好了API接口,但调试环境花了将近一周的时间。主要就是生产环境中kerberos认证通过后hive账号权限的改动引起的keytab认证文件重新下载;再一个就是hive账号查询权限问题,一开始中台的人说一切没问题,咱就只能在自己代码里找问题,但其实后来我才在官网查到是需要他们配置的。