當前的項目中, 涉及到了hive-jdbc/odbc這塊, 因此把這幾天所調研的資料作一份總結.
本文講解hive-jdbc/hive-odbc的實現, 以期對jdbc/odbc規范和實現有個較深入的理解和看法.
在具體講述hive-jdbc之前,首先講解一下hive的整體架構
*) hive的整體架構
這幅圖很清晰的表明了hive的整體架構, 以及各個組件扮演的角色, 這邊專注於講解下hive-jdbc/hive-odbc如何實現,並如何與hiveserver進行交互.
*) 對hive-jdbc的理解和認識
JDBC/ODBC兩者皆是通過hiveclient與hiveserver保持通訊的,借助thrfit rpc協議來實現交互。
hiveserver里面的session是socket連接級別,不是全局維護的,因此hiveserver的部署屬於無狀態節點,其HA部署方式簡單采用多節點部署即可.
在hive-0.12源碼目錄下,odbc是c/c++編寫的源碼,大致瀏覽了下,簡單易懂,但都是與hiveserver交互的那部分代碼,看不到任何與ODBC協議接口相關的內容。
同時對比了下hive-jdbc的源碼, 同一個模塊下有兩份hive-jdbc源碼,分別為org.apache.hadoop.hive.jdbc, org.apache.hive.jdbc, 前者對應hiveserver ,后者對應hiveserver2 實現了tcliservice.thrift接口, hiveserver2加強了並發、認證等功能,同時對open api更友好。
JDBC是java database connection的規范,它定義了一系列java訪問各類db的訪問接口,因此hive-jdbc其實本質上是扮演一個協議轉換的角色,把jdbc的標准協議轉換為訪問HiveServer服務的協議. hive-jdbc除了扮演網絡協議轉化的工作, 並不承擔他的工作, 比如sql的合法性校驗和解析,一律忽略.
jdbc的統一接口
public interface Connection extends Wrapper { Statement createStatement() throws SQLException; void commit() throws SQLException; Statement createStatement() throws SQLException; void close() throws SQLException; } public interface Statement extends Wrapper { boolean execute(String sql) throws SQLException; ResultSet getResultSet() throws SQLException; } public interface ResultSet extends Wrapper { Statement createStatement() throws SQLException; String getString(int columnIndex) throws SQLException; }
hive-jdbc里最重要的3個類conection, statement, resultset.
conection對應hiveclient的創建, statement則對應hiveclient具體sql調用接口執行, resultset對應數據的讀取(采用lazy的方式 + 分批批量讀取的策略, 對涉及大數據返回結果的查詢sql非常友好),因為hiveclient是個長連接, 而thrift rpc是個request/response的服務方式, 一個sql會對應多次rpc訪問, 因此session扮演了很重要的角色.
其對應的服務接口如下所示:
public interface ThriftHiveMetastore.Iface { // 對應 hive-jdbc, Statement能訪問的接口,用於sql的執行 public void execute(String query) throws HiveServerException, org.apache.thrift.TException; // 對應hive-jdbc, ResultSet涉及的數據讀取的接口 public String fetchOne() throws HiveServerException, org.apache.thrift.TException; public List<String> fetchN(int numRows) throws HiveServerException, org.apache.thrift.TException; public List<String> fetchAll() throws HiveServerException, org.apache.thrift.TException; }
*) hive-server的一點看法
Thrift最常用的還是當作rpc服務使用,請求沒有session的概念,這邊hiveserver采用thrift是采用worker thread pool來處理,它選用了ThreadPoolServer(One thread per connection)這種thrift提供的服務模型中,最簡單的,也是最適合長連接並需要維護session的應用場景。單另一方面, 由於hiveserver沒有zookeeper作協調, 而連接方式又是采用長鏈接, 因此可能會出現集群負載不均衡的情況. 而且,據之前對thrift的認識, thrift對超時控制缺少支持, 這方便在hive-jdbc的實現中,好像也有所體現. 個人的看法.
參考資料:
https://cwiki.apache.org/confluence/display/Hive/HiveClient
www.cnblogs.com/sharpxiajun/archive/2013/06/02/3114180.html