使用ZooKeeper连接串JDBC连接Hive失败(附异常日志)
首先看你提供的日志,关键错误点在这里:
Will try to open client transport with JDBC Uri: jdbc:hive2://hive.server2.authentication=NONE;hive.server2.transport.mode=binary;.../;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2
客户端把ZooKeeper返回的HiveServer2配置参数错误地解析成了主机地址,而不是提取其中的sandbox-hdp.hortonworks.com:10000来建立连接,这直接导致了后续的NullPointerException(因为TSocket无法用一串配置键值对作为主机名)。
下面是针对性的排查和修复步骤:
1. 匹配Hive JDBC驱动版本到HDP 2.6.4
HDP 2.6.4对应的Hive版本是1.2.1000,如果你用了更高版本的Hive JDBC驱动(比如2.x+),就会出现这种ZK元数据解析不兼容的问题。你需要使用和HDP Sandbox完全匹配的驱动版本:
- 驱动坐标(Maven):
org.apache.hive:hive-jdbc:1.2.1000.2.6.4.0-91 - 确保排除掉冲突的依赖(比如高版本的curator、zookeeper客户端),保持依赖和HDP集群一致。
2. 修正ZK模式的JDBC连接串格式
你的连接串写法有个小问题:如果要指定数据库,应该把数据库名放在ZK地址之后的斜杠后面,而不是通过无效的String.format占位符(你的format字符串里没有%s,所以database参数根本没生效)。正确的连接串格式应该是:
// 如果需要指定数据库 val jdbcUrl = "jdbc:hive2://sandbox-hdp.hortonworks.com:2181/%s;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2".format(database) // 如果不需要指定数据库 val jdbcUrl = "jdbc:hive2://sandbox-hdp.hortonworks.com:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2"
3. 检查HiveServer2的ZK注册配置
登录HDP Sandbox,检查Hive的配置项:
- 确认
hive.server2.zookeeper.namespace设置为hiveserver2(和你的连接串一致) - 检查
hive.server2.zookeeper.publish.configs是否设置为false:如果这个参数是true,HiveServer2会把所有配置参数注册到ZK,旧版本的JDBC驱动无法正确解析这些参数,只会把它们当成主机地址。
4. 验证ZK中的HiveServer2注册节点
在Sandbox里执行zkCli.sh,连接到本地ZK:
zkCli.sh -server sandbox-hdp.hortonworks.com:2181
然后查看/hiveserver2下的子节点:
ls /hiveserver2 get /hiveserver2/<子节点名称>
正常情况下,返回的内容应该是类似thrift://sandbox-hdp.hortonworks.com:10000的Thrift URI,而不是一堆配置键值对。如果返回的是配置参数,说明HiveServer2的注册配置有问题,需要调整hive.server2.zookeeper.publish.configs为false后重启HiveServer2。
按照这些步骤排查,应该能解决ZK模式的连接问题。
内容的提问来源于stack exchange,提问作者Ajax Sandell Peterman

