Hive JDBC 连接问题

Posted

技术标签:

【中文标题】Hive JDBC 连接问题【英文标题】:Hive JDBC connection problems 【发布时间】:2018-05-06 01:34:25 【问题描述】:

我正在尝试通过带有 kerberos 身份验证的 JDBC 连接到 Hive2 服务器。经过多次尝试使其工作,我无法让它与 Cloudera 驱动程序一起工作。

如果有人能帮我解决问题,我将不胜感激。

我有这个方法:

    private Connection establishConnection() 
    final String driverPropertyClassName = "driver";
    final String urlProperty = "url";
    Properties hiveProperties = config.getMatchingProperties("hive.jdbc");
    String driverClassName = (String) hiveProperties.remove(driverPropertyClassName);
    String url = (String) hiveProperties.remove(urlProperty);
    Configuration hadoopConfig = new Configuration();
    hadoopConfig.set("hadoop.security.authentication", "Kerberos");
    String p = config.getProperty("hadoop.core.site.path");
    Path path = new Path(p);
    hadoopConfig.addResource(path);
    UserGroupInformation.setConfiguration(hadoopConfig);

    Connection conn = null;
    if (driverClassName != null) 
        try 
            UserGroupInformation.loginUserFromKeytab(config.getProperty("login.user"), config.getProperty("keytab.file"));
            Driver driver = (Driver) Class.forName(driverClassName).newInstance();
            DriverManager.registerDriver(driver);
            conn = DriverManager.getConnection(url, hiveProperties);
         catch (Throwable e) 
            LOG.error("Failed to establish Hive connection", e);
        
    
    return conn;

服务器的 URL,我从 Cloudera documentation 中描述的格式的属性中获取

我遇到了一个异常:

2018-05-05 18:26:49 ERROR HiveReader:147 - Failed to establish Hive connection
java.sql.SQLException: [Cloudera][HiveJDBCDriver](500164) Error initialized or created transport for authentication: Peer indicated failure: Unsupported mechanism type PLAIN.
    at com.cloudera.hiveserver2.hivecommon.api.HiveServer2ClientFactory.createTransport(Unknown Source)
    at com.cloudera.hiveserver2.hivecommon.api.ZooKeeperEnabledExtendedHS2Factory.createClient(Unknown Source)
...

我认为它缺少 AuthMech 属性并将 AuthMech=1 添加到 URL。现在我得到:

java.sql.SQLNonTransientConnectionException: [Cloudera][JDBC](10100) Connection Refused: [Cloudera][JDBC](11640) Required Connection Key(s): KrbHostFQDN, KrbServiceName; [Cloudera][JDBC](11480) Optional Connection Key(s): AsyncExecPollInterval, AutomaticColumnRename, CatalogSchemaSwitch, DecimalColumnScale, DefaultStringColumnLength, DelegationToken, DelegationUID, krbAuthType, KrbRealm, PreparedMetaLimitZero, RowsFetchedPerBlock, SocketTimeOut, ssl, StripCatalogName, transportMode, UseCustomTypeCoercionMap, UseNativeQuery, zk
    at com.cloudera.hiveserver2.exceptions.ExceptionConverter.toSQLException(Unknown Source)
    at com.cloudera.hiveserver2.jdbc.common.BaseConnectionFactory.checkResponseMap(Unknown Source)
    ...

但 KrbHostFQDN 已按照文档要求在主体属性中指定。

是我遗漏了什么还是此文档有误?

【问题讨论】:

我已删除您的咆哮,因为它与您的问题没有直接关系。我可以理解处理这样的问题可能会令人沮丧,但是在你的问题中这样发泄可能会关闭熟悉 hive 和 cloudera 的人,从而导致获得好的答案的机会减少。 【参考方案1】:

以下是 Impala 中类似的问题陈述之一(只是 JDBC 引擎更改其他相同),通过在 JDBC 连接字符串本身中设置“KrbHostFQDN”相关属性来解决。

尝试使用以下网址。希望对你有用。

String jdbcConnStr = "jdbc:impala://myserver.mycompany.corp:21050/default;SSL=1;AuthMech=1;KrbHostFQDN=myserver.mycompany.corp;KrbRealm=MYCOMPANY.CORP;KrbServiceName=impala"

我想如果您不使用 SSL=1 而只使用 Kerberos,您只需从连接字符串中删除该部分,而不必担心在 java 密钥库中设置 SSL 证书,这又是一个麻烦。

但是,为了让 Kerberos 正常工作,我们做了以下工作:

安装 MIT Kerberos 4.0.1,它是一个 kerberos 票证管理器。 (适用于 Windows)

每次您启动连接时,此票证管理器都会要求您进行身份验证,创建票证并将其存储在 kerberos_ticket.dat 二进制文件中,该文件的位置可以通过某种方式进行配置,但我不记得具体是如何配置的。

最后,在启动您的 JAVA 应用程序之前,您必须设置一个环境变量 KRB5CCNAME=C:/path/to/kerberos_ticket.dat。在您的 Java 应用程序中,您可以通过执行 System.out.println( "KRB5CCNAME = " + System.getenv( "KRB5CCNAME" ) ) 来检查变量是否正确设置。如果您正在使用 eclipse 或其他 IDE,您甚至可能需要关闭 IDE,设置环境变量并重新启动 IDE。

注意:最后一点非常重要,我观察到如果这个变量没有正确设置,连接将无法建立......

在 Linux 中,代替 MIT Kerberos 4.0.1,有一个名为 kinit 的程序可以做同样的事情,但没有图形界面,这更方便自动化。

【讨论】:

可以在这里添加例外吗? 我收到以下异常:javax.security.sasl.SaslException:GSS 启动失败 [由 GSSException 引起:未提供有效凭据(机制级别:创建凭据失败。(63)- 无服务凭据)] 在 org.apache.thrift.transport.TSaslClientTransport.handleSaslStartMessage(TSaslClientTransport.java:94) 在 org.apache.thrift.transport 的 com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:211) .TSaslTransport.open(TSaslTransport.java:271) 在与 com.cloudera.hive.jdbc4.HS2Driver 斗争了两个星期后,我放弃了,回到了 org.apache.hive.jdbc.HiveDriver。有了这个,我几乎可以立即建立连接。看起来 Cloudera 驱动程序还没有准备好迎接黄金时段。【参考方案2】:

我想把它放在评论中,但评论太长了,所以我把它放在这里: 我尝试了您的建议,但又遇到了另一个例外:

java.sql.SQLException: [Cloudera]HiveJDBCDriver 错误 使用票证缓存创建登录上下文:无法获取主体 身份验证名称。

可能是我的问题是,我没有设置环境变量 KRB5CCNAME。 老实说,我以前从未听说过。 该票证文件中应​​该包含什么。 但是,我的主要方法中确实有以下行:

System.setProperty("java.security.krb5.conf", "path/to/krb5.conf");

应该使用哪个

UserGroupInformation.loginUserFromKeytab(config.getProperty("login.user"), config.getProperty("keytab.file"));

获取kerberos票据。

【讨论】:

【参考方案3】:

要解决此问题,请为您在系统中使用的 Java 版本更新 Java Cryptography Extension。

    这里是您可以为Java 1.7 下载 JCE 的链接 解压缩并覆盖 $JDK_HOME/jre/lib/security 中的这些文件 重新启动计算机。

【讨论】:

以上是关于Hive JDBC 连接问题的主要内容,如果未能解决你的问题,请参考以下文章

通过 Java JDBC 连接 Hive

使用JDBC 连接 hive 报错 Invalid status 72

Hive JDBC 连接超时

JAVA 中的 Hive JDBC 连接

通过 Knox 获取到 Hive 的 JDBC 连接时出错

无法使用 Zookeeper 连接字符串通过 JDBC 连接到 Hive