hadoop元件---資料倉庫(五)---通過JDBC連線hive的thrift或者hiveserver2
我們在上一篇文章中已經學習了Hive的常用命令,但是如果使用其他的語言如何跟Hive進行互動呢。
Thrift簡介
Hive擁有HiveServer(Thrift)或者Hiveserver2元件,提供了JDBC驅動服務,使得我們可以用Java程式碼或者Python來連線Hive並進行一些關係型資料庫的sql語句查詢等操作。
HiveServer或者HiveServer2都是基於Thrift的,但HiveSever有時被稱為Thrift server,而HiveServer2卻不會。既然已經存在HiveServer為什麼還需要HiveServer2呢?這是因為HiveServer不能處理多於一個客戶端的併發請求,這是由於HiveServer使用的Thrift介面所導致的限制,不能通過修改HiveServer的程式碼修正。因此在Hive-0.11.0版本中重寫了HiveServer程式碼得到了HiveServer2,進而解決了該問題。HiveServer2支援多客戶端的併發和認證,為開放API客戶端如JDBC、ODBC提供了更好的支援。
既然HiveServer2提供了更強大的功能,將會對其進行著重學習,但也會簡單瞭解一下HiveServer的使用方法。在命令中輸入
hive --service help
結果如下
我們可以看到上邊輸出項Server List,裡邊顯示出Hive支援的服務列表,beeline cli help hiveserver2 hiveserver hwi jar lineage metastore metatool orcfiledump rcfilecat,下面介紹最有用的一些服務
1、cli:是Command Line Interface 的縮寫,是Hive的命令列介面,用的比較多,是預設服務,直接可以在命令列裡使用
2、hiveserver:這個可以讓Hive以提供Thrift服務的伺服器形式來執行,可以允許許多個不同語言編寫的客戶端進行通訊,使用需要啟動HiveServer服務以和客戶端聯絡,我們可以通過設定HIVE_PORT環境變數來設定伺服器所監聽的埠,在預設情況下,埠號為10000,這個可以通過以下方式來啟動Hiverserver:
bin/hive --service hiveserver -p 10002
其中-p引數也是用來指定監聽埠的
3、hwi:其實就是hive web interface的縮寫它是hive的web藉口,是hive cli的一個web替代方案
4、jar:與hadoop jar等價的Hive介面,這是執行類路徑中同時包含Hadoop 和Hive類的Java應用程式的簡便方式
5、metastore:在預設的情況下,metastore和hive服務執行在同一個程序中,使用這個服務,可以讓metastore作為一個單獨的程序執行,我們可以通過METASTOE——PORT來指定監聽的埠號
從結果可以瞭解到,可以使用
hive <parameters> --service serviceName <serviceparameters>
啟動特定的服務,如cli、hiverserver、hiveserver2等。
在命令列輸入
hive --service hiveserver –help
hive --service hiveserver2 –help
檢視hiveserver的幫助資訊:
從圖中可以看到有些版本hive已經不支援hiveserver了,只能使用hiveserver2。
啟動hiveserver2
使用命令啟動
hive --service hiveserver2
如圖:
hiveserver2配置
配置檔案可以使用如下命令查詢:
whereis hive
如圖:
Hiveserver2允許在配置檔案hive-site.xml中進行配置管理,常用引數有:
hive.server2.thrift.min.worker.threads– 最小工作執行緒數,預設為5。
hive.server2.thrift.max.worker.threads – 最小工作執行緒數,預設為500。
hive.server2.thrift.port– TCP 的監聽埠,預設為10000。
hive.server2.thrift.bind.host– TCP繫結的主機,預設為localhost。
也可以設定環境變數HIVE_SERVER2_THRIFT_BIND_HOST和HIVE_SERVER2_THRIFT_PORT覆蓋hive-site.xml設定的主機和埠號。
hive.server2.thrift.port 10000
hive.server2.thrift.bind.host 192.168.48.130
從Hive-0.13.0開始,HiveServer2支援通過HTTP傳輸訊息,該特性當客戶端和伺服器之間存在代理中介時特別有用。與HTTP傳輸相關的引數如下:
hive.server2.transport.mode – 預設值為binary(TCP),可選值HTTP。
hive.server2.thrift.http.port– HTTP的監聽埠,預設值為10001。
hive.server2.thrift.http.path – 服務的端點名稱,預設為 cliservice。
hive.server2.thrift.http.min.worker.threads– 服務池中的最小工作執行緒,預設為5。
hive.server2.thrift.http.max.worker.threads– 服務池中的最小工作執行緒,預設為500。
預設情況下,HiveServer2以提交查詢的使用者執行查詢(true),如果hive.server2.enable.doAs設定為false,查詢將以執行hiveserver2程序的使用者執行。
<property>
<name>hive.server2.enable.doAs</name>
<value>true</value>
</property>
為了防止非加密模式下的記憶體洩露,可以通過設定下面的引數為true禁用檔案系統的快取:
fs.hdfs.impl.disable.cache – 禁用HDFS檔案系統快取,預設值為false。
fs.file.impl.disable.cache – 禁用本地檔案系統快取,預設值為false。
測試hiveserver2
hive自帶了一個thrift的客戶端——-beeline
開啟beeline
使用命令
beeline
連線hiveserver2
使用命令
!connect jdbc:hive2://host253:10000
(host253是hiveserver2所啟動的那臺主機名,埠預設是10000)
如果是在hiveserver2所啟動的那臺主機進行操作也可以使用命令
!connect jdbc:hive2://localhost:10000
有可能需要輸入當前linux使用者名稱和密碼。
正常連線上之後會出現
0: jdbc:hive2://host253:10000>
這時可以嘗試操作資料庫了,使用命令
show databases;
結果如下圖:
HiveServer2 Thrift API
用Java程式碼通過JDBC連線Hiveserver2
新增依賴的包
依賴的jar包有以下幾個:
hadoop-2.2.0/share/hadoop/common/hadoop-common-2.2.0.jar
$HIVE_HOME/lib/hive-exec-0.11.0.jar
$HIVE_HOME/lib/hive-jdbc-0.11.0.jar
$HIVE_HOME/lib/hive-metastore-0.11.0.jar
$HIVE_HOME/lib/hive-service-0.11.0.jar
$HIVE_HOME/lib/libfb303-0.9.0.jar
$HIVE_HOME/lib/commons-logging-1.0.4.jar
$HIVE_HOME/lib/slf4j-api-1.6.1.jar
如果是使用Maven,則加入依賴如下:
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>0.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.2.0</version>
</dependency>
Java程式碼如下
package com.test;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.DriverManager;
public class HiveJdbcTest {
private static String driverName = "org.apache.hive.jdbc.HiveDriver";
public static void main(String[] args) throws SQLException {
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
Connection con = DriverManager.getConnection("jdbc:hive2://localhost:10000/default", "zzq", "12345");
Statement stmt = con.createStatement();
String tableName = "students";
stmt.execute("drop table if exists " + tableName);
stmt.execute("create table " + tableName + " (key int, value string)");
System.out.println("Create table success!");
// show tables
String sql = "show tables '" + tableName + "'";
System.out.println("Running: " + sql);
ResultSet res = stmt.executeQuery(sql);
if (res.next()) {
System.out.println(res.getString(1));
}
// describe table
sql = "describe " + tableName;
System.out.println("Running: " + sql);
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(res.getString(1) + "\t" + res.getString(2));
}
sql = "select * from " + tableName;
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(String.valueOf(res.getInt(1)) + "\t" + res.getString(2));
}
sql = "select count(1) from " + tableName;
System.out.println("Running: " + sql);
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(res.getString(1));
}
}
}
Hiveserver1和hiveserver2的JDBC區別
HiveServer version
HiveServer2
HiveServer1
Connection URL
jdbc:hive2://:
jdbc:hive://:
Driver Class
org.apache.hive.jdbc.HiveDriver
org.apache.hadoop.hive.jdbc.HiveDriver
用Java程式碼通過JDBC連線Hiveserver
我們前面已經熟悉了用Java程式碼通過JDBC連線Hiveserver2,也知道了Hiveserver1和hiveserver2的JDBC區別,連線Hiveserver只需要修改相應的URL和驅動即可。
也就是
private static String driverName = "org.apache.hive.jdbc.HiveDriver";
改為
private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";
Connection con = DriverManager.getConnection("jdbc:hive2://localhost:10002/default", "zzq", "12345");
改為
Connection con = DriverManager.getConnection("jdbc:hive://localhost:10002/default", "zzq", "12345");
Java程式碼如下
package com.test;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.DriverManager;
public class HiveJdbcTest {
private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";
public static void main(String[] args) throws SQLException {
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.exit(1);
}
Connection con = DriverManager.getConnection("jdbc:hive://localhost:10002/default", "zzq", "12345");
Statement stmt = con.createStatement();
String tableName = "students";
stmt.execute("drop table if exists " + tableName);
stmt.execute("create table " + tableName + " (key int, value string)");
System.out.println("Create table success!");
// show tables
String sql = "show tables '" + tableName + "'";
System.out.println("Running: " + sql);
ResultSet res = stmt.executeQuery(sql);
if (res.next()) {
System.out.println(res.getString(1));
}
// describe table
sql = "describe " + tableName;
System.out.println("Running: " + sql);
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(res.getString(1) + "\t" + res.getString(2));
}
sql = "select * from " + tableName;
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(String.valueOf(res.getInt(1)) + "\t" + res.getString(2));
}
sql = "select count(1) from " + tableName;
System.out.println("Running: " + sql);
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(res.getString(1));
}
}
}