下面介紹1下我對hive幾種使用方式的理解,首先是hive的元
數(shù)據(jù)庫,它分為3種情勢的,
第1種是內(nèi)嵌的derby數(shù)據(jù)庫,這類方式由于derby會在當(dāng)前目錄創(chuàng)建1個目錄,所以智能啟動1個hive實(shí)例,
第2種方式是使用遠(yuǎn)程數(shù)據(jù)庫,也就是使用1個關(guān)系
數(shù)據(jù)庫系統(tǒng),例如mysql等(目前只測試了mysql),hive通過jdbc連接mysql獲得元數(shù)據(jù)信息,
還有1種方式是hive自帶的metaserver,這個server是用來關(guān)系元數(shù)據(jù)的,相當(dāng)于在真實(shí)的元數(shù)據(jù)管理器之前又搭了1個服務(wù)。
在使用的進(jìn)程中主要有兩種方式使用hive,
第1種就是僅僅把hive作為1個可以對文件使用SQL查詢的根據(jù)來使用,也就是直接使用hive命令行,亦或在程序中使用hive提供的函數(shù)啟動,在這類情況下我們只需要配置好hive元數(shù)據(jù)
服務(wù)器(告知hive存儲了哪些
數(shù)據(jù)庫和表和其屬性)和hive的數(shù)據(jù)倉庫目錄(1般是1個HDFS的目錄),經(jīng)過測試數(shù)據(jù)倉庫的目錄只是在創(chuàng)建
數(shù)據(jù)庫的時候有作用,在創(chuàng)建表的時候會在所在
數(shù)據(jù)庫的目錄下創(chuàng)建表的目錄,另外還需要指定hadoop的配置文件和jar包,畢竟hive依賴于hadoop履行任務(wù)。
第2種方式就是講hive作為1個提供了SQL接口的數(shù)據(jù)庫使用,我們可以通過jdbc的方式訪問它,類似于使用mysql的方式,本文主要介紹的就是如何配置這個
服務(wù)器并且使用hive自帶的客戶端和使用jdbc的方式連接使用。
接下來就是對hive進(jìn)行環(huán)境配置了,對hive,我的1般使用方式是使用遠(yuǎn)程的mysql做為源數(shù)據(jù)
服務(wù)器。而不使用hive自帶的matestore
服務(wù)器,貌似后者能支持更大的并發(fā),這個暫時沒需求就簡單的來,除元
數(shù)據(jù)庫還有1個重點(diǎn)就是數(shù)據(jù)倉庫地址,我配置的我的個人用戶intern的目錄/user/intern,具體配置以下:
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/intern/</value>
<description>location of default database for the warehouse</description>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://127.0.0.1:3306/HIVE</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
<description>password to use against metastore database</description>
</property>
另外,這里對hive元數(shù)據(jù)的創(chuàng)建還需要注意1下,1般情況下我們會選擇使用utf8作為
數(shù)據(jù)庫默許的字符集(應(yīng)當(dāng)是為了支持中文),但是如果你使用utf8字符集hive會出現(xiàn)很多稀里糊涂的毛病,讓人摸不到頭腦,
所以需要再創(chuàng)建hive數(shù)據(jù)庫的時候需要指定字符集為latin1,另外還可讓hive自動幫你創(chuàng)建(我沒有嘗試過,不知道是不是可行)。
接下來還需要配置1些關(guān)于kerberos認(rèn)證的東西,具體的配置內(nèi)容以下:
<property>
<name>hive.server2.authentication</name>
<value>KERBEROS</value>
<description>
Client authentication types.
NONE: no authentication check
LDAP: LDAP/AD based authentication
KERBEROS: Kerberos/GSSAPI authentication
CUSTOM: Custom authentication provider
(Use with property hive.server2.custom.authentication.class)
PAM: Pluggable authentication module.
</description>
</property>
<property>
<name>hive.server2.authentication.kerberos.principal</name>
<value>hive/xxx@HADOOP.XXX.COM</value>
<description>
Kerberos server principal
</description>
</property>
<property>
<name>hive.server2.authentication.kerberos.keytab</name>
<value>/home/hzfengyu/hive.keytab</value>
<description>
Kerberos keytab file for server principal
</description>
</property>
這3個配置項分別是配置hiveserver2的認(rèn)證方式,如果配置不得當(dāng)客戶端會出現(xiàn)很多問題,默許情況下認(rèn)證方式是CUSTOM,這里我們配置成KERBEROS,然后配置kerberos認(rèn)證需要的keytab文件和principal,1般情況下我們履行kinit也就是需要這兩樣?xùn)|西,不過不同的是這里的principal需要指定完成的,而不只是@符號前面的東西(kinit的時候只指定前面的東西就能夠了),另外需要注意的是這里的keytab對應(yīng)的用戶必須在hadoop上具有可代理履行的權(quán)限,這是hiveserver2所需要的,也就是說其實(shí)hiveserver2只是1個指定代理的服務(wù)器,不同的用戶通過jdbc連接到hiveserver2,根據(jù)客戶端不同的keytab用戶代理不同的用戶履行具體的操作。如果該用戶沒有代理的權(quán)限,在使用jdbc和hiveserver2建立連接的時候會出現(xiàn)認(rèn)證毛病,毛病的堆棧為:
15/05/01 17:32:33 [main]: ERROR transport.TSaslTransport: SASL negotiation failure
javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7) - UNKNOWN_SERVER)]
at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:212)
at org.apache.thrift.transport.TSaslClientTransport.handleSaslStartMessage(TSaslClientTransport.java:94)
at org.apache.thrift.transport.TSaslTransport.open(TSaslTransport.java:253)
at org.apache.thrift.transport.TSaslClientTransport.open(TSaslClientTransport.java:37)
at org.apache.hadoop.hive.thrift.client.TUGIAssumingTransport$1.run(TUGIAssumingTransport.java:52)
at org.apache.hadoop.hive.thrift.client.TUGIAssumingTransport$1.run(TUGIAssumingTransport.java:49)
at java.security.AccessController.doPrivileged(Native Method)
這里我用的是hive用戶,這個用戶具有代理權(quán)限,而我使用jdbc連接的機(jī)器使用的用戶是intern,首先在hive機(jī)器上履行啟動hiveserver2的命令:
./bin/hive --service hiveserver2
然后再客戶真?zhèn)€機(jī)器上通過hive自帶的beeline進(jìn)行連接:
./bin/beeline
然后使用connect命令連接hiveserver2:
beeline> !connect jdbc:hive2://hiveserver2-ip:10000/foodmart;principal=hive/xxx@HADOOP.XXX.COM;
scan complete in 34ms
Connecting to jdbc:hive2://bitest0.server.163.org:10000/foodmart;principal=hive/app⑵0.photo.163.org@HADOOP.HZ.NETEASE.COM;
Enter username for jdbc:hive2://bitest0.server.163.org:10000/foodmart;principal=hive/app⑵0.photo.163.org@HADOOP.HZ.NETEASE.COM;:
Enter password for jdbc:hive2://bitest0.server.163.org:10000/foodmart;principal=hive/app⑵0.photo.163.org@HADOOP.HZ.NETEASE.COM;:
Connected to: Apache Hive (version 0.14.0)
Driver: Hive JDBC (version 0.14.0)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://bitest0.server.163.org:10000/>
連接的時候需要指定jdbc的url(默許的端口號為10000,也能夠在hiveserver2的配置文件中配置),另外還需要制定
服務(wù)器的principal,也就是在上面配置的那個hive.server2.authentication.kerberos.principal,而客戶端用戶使用的用戶就是客戶真?zhèn)€當(dāng)前用戶,可使用klist查看。
除使用自帶的beeline連接,還可以在程序中使用jdbc進(jìn)行連接,測試代碼以下:
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
public class TestHive {
public static void main(String[] args) throws SQLException {
try {
Class.forName("org.apache.hive.jdbc.HiveDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Configuration conf = new Configuration();
conf.setBoolean("hadoop.security.authorization", true);
conf.set("hadoop.security.authentication", "kerberos");
UserGroupInformation.setConfiguration(conf);
try {
UserGroupInformation.loginUserFromKeytab("intern/bigdata", "C:UsersAdministratorDesktopintern.keytab");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Connection conn = DriverManager
.getConnection(
"jdbc:hive2://hiveserver2-ip:10000/foodmart;principal=hive/xxx@HADOOP.XXX.COM;User=;Password=;",
"", "");
Statement stmt = conn.createStatement();
String sql = "select * from account limit 10";
System.out.println("Running: " + sql);
ResultSet res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(String.valueOf(res.getInt(1)) + " "
+ res.getString(2));
}
}
}
好了,這里說完了如何搭建1個使用kerberos認(rèn)證的hiveserver2,下1篇在介紹如何使用hive作為mondrian的數(shù)據(jù)源履行MDX查詢。
最后的最后,介紹1下遇到的1個最大的問題,在配置kerberos認(rèn)證的時候,我使用的hive版本是0.13.1,依照上面的配置出現(xiàn)了以下的問題:
2015-04⑶0 17:02:22,602 ERROR [Thread⑹]: thrift.ThriftCLIService (ThriftBinaryCLIService.java:run(93)) - Error:
java.lang.NoSuchFieldError: SASL_PROPS
at org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge20S.getHadoopSaslProperties(HadoopThriftAuthBridge20S.java:126)
at org.apache.hive.service.auth.HiveAuthFactory.getSaslProperties(HiveAuthFactory.java:116)
at org.apache.hive.service.auth.HiveAuthFactory.getAuthTransFactory(HiveAuthFactory.java:133)
at org.apache.hive.service.cli.thrift.ThriftBinaryCLIService.run(ThriftBinaryCLIService.java:43)
at java.lang.Thread.run(Thread.java:701)
2015-04⑶0 17:02:22,605 INFO [Thread[Thread⑺,5,main]]: delegation.AbstractDelegationTokenSecretManager (AbstractDelegationTokenSecretManager.java:updateCurrentKey(
222)) - Updating the current master key for generating delegation tokens
2015-04⑶0 17:02:22,612 INFO [Thread⑶]: server.HiveServer2 (HiveStringUtils.java:run(623)) - SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down HiveServer2 at bitest0.server.163.org/10.120.36.85
************************************************************/
最后在google找了1下相干的毛病,發(fā)現(xiàn)了HIVE的這個bug:https://issues.apache.org/jira/browse/HIVE⑺620
不知道我遇到的是否是這個問題,但是不管如何就是解決不了這個問題(其實(shí)可以說是束手無策),我就換了1下hive的版本,上看說在0.14.0已解決,我就換成了新的版本,果然這個問題不再出現(xiàn)了,至于究竟是否由這個bug引發(fā)也不得而知了。