溫馨提示:如果使用電腦查看圖片不清晰,可以使用手機打開文章單擊文中的圖片放大查看高清原圖。
Fayson的github: https://github.com/fayson/cdhproject
提示:代碼塊部分可以左右滑動查看噢
1
文檔編寫目的
前面Fayson介紹了《如何使用Java API訪問CDH的Kudu》,文章是在非安全環境下實現,隨着對集羣安全要求的提高,在Kerberos環境下的使用API訪問Kudu也會有一些變化,本篇文章Fayson主要介紹如何使用Java代碼訪問Kerberos環境下的Kudu。
- 內容概述
1.環境準備
2.Kerberos環境示例代碼及運行
3.總結
- 測試環境
1.CDH版本爲5.15.0
2.OS爲Redhat7.2
3.Kudu版本爲1.7.0
- 前置條件
1.CDH集羣運行正常
2.集羣已啓用Kerberos
2
環境準備
使用IDE工具通過Maven創建一個Java工程,具體創建過程就不詳細描述了。
1.在工程的pom.xml文件中增加如下依賴
<dependency> <groupId>org.apache.kudu</groupId> <artifactId>kudu-client</artifactId> <version>1.7.0-cdh5.15.2</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.6.0-cdh5.15.0</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.6.0-cdh5.15.0</version> </dependency>
2.集羣爲Kerberos,需要導出一個keytab文件用於訪問HDFS,導出步驟如下
在CMD命令行執行如下命令導出AD中用戶的keytab文件
ktpass -princ hdfs/[email protected] -mapuser hdfs/admin -pass 123!QAZ -out hdfsadmin.keytab -crypto RC4-HMAC-NT
(可左右滑動)
導出的keytab文件會在當前命令執行目錄。
3.獲取集羣krb5.conf文件,內容如下
[root@cdh4 ~]# more /etc/krb5.conf # Configuration snippets may be placed in this directory as well includedir /etc/krb5.conf.d/ includedir /var/lib/sss/pubconf/krb5.include.d/ [logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] dns_lookup_realm = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = true rdns = true default_realm = FAYSON.COM #default_ccache_name = KEYRING:persistent:%{uid} [realms] FAYSON.COM = { kdc = adserver.fayson.com admin_server = adserver.fayson.com } [domain_realm] .fayson.com = FAYSON.COM fayson.com = FAYSON.COM
(可左右滑動)
4.配置hosts文件,確保本地開發環境與集羣所有節點通且端口均放通
5.通過Cloudera Manager下載HDFS客戶端配置
6.將上述準備的配置文件及keytab等信息拷貝至本地目錄或工程中,Fayson的工程目錄結構如下:
3
第一標題
1.ClientUtils類主要提供客戶端初始化方法,內容如下:
package com.cloudera.utils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation; import java.util.Properties; /** * package: com.cloudera.utils * describe: 客戶端工具類 * creat_user: Fayson * email: [email protected] * creat_date: 2018/11/14 * creat_time: 下午10:17 * 公衆號:Hadoop實操 */ public class ClientUtils { /** * 初始化訪問Kerberos訪問 * @param debug 是否啓用Kerberos的Debug模式 */ public static void initKerberosENV(Boolean debug) { try { Properties properties = new Properties(); properties.load(ClientUtils.class.getClass().getResourceAsStream("/client.properties ")); System.setProperty("java.security.krb5.conf", properties.getProperty("krb5.conf.path")); System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); if (debug) System.setProperty("sun.security.krb5.debug", "true"); Configuration configuration = new Configuration(); configuration.addResource(ClientUtils.class.getClass().getResourceAsStream("/hdfs-client-kb/core-site.xml")); configuration.addResource(ClientUtils.class.getClass().getResourceAsStream("/hdfs-client-kb/hdfs-site.xml")); UserGroupInformation.setConfiguration(configuration); UserGroupInformation.loginUserFromKeytab(properties.getProperty("kerberos.user"), properties.getProperty("kerberos.keytab.path")); System.out.println(UserGroupInformation.getCurrentUser()); } catch(Exception e) { e.printStackTrace(); } } }
(可左右滑動)
2.KuduUtils用於操作Kudu的工具類,建表、查詢數據、刪除表等操作
package com.cloudera.utils; import com.cloudera.RandomUserInfo; import org.apache.kudu.ColumnSchema; import org.apache.kudu.Schema; import org.apache.kudu.Type; import org.apache.kudu.client.*; import java.util.ArrayList; import java.util.List; /** * package: com.cloudera.utils * describe: TODO * creat_user: Fayson * email: [email protected] * creat_date: 2018/11/15 * creat_time: 上午12:31 * 公衆號:Hadoop實操 */ public class KuduUtils { /** * 使用Kudu API創建一個Kudu表 * @param client * @param tableName */ public static void createTable(KuduClient client, String tableName) { List<ColumnSchema> columns = new ArrayList<>(); //在添加列時可以指定每一列的壓縮格式 columns.add(new ColumnSchema.ColumnSchemaBuilder("id", Type.STRING).key(true). compressionAlgorithm(ColumnSchema.CompressionAlgorithm.SNAPPY).build()); … Schema schema = new Schema(columns); CreateTableOptions createTableOptions = new CreateTableOptions(); List<String> hashKeys = new ArrayList<>(); hashKeys.add("id"); int numBuckets = 8; createTableOptions.addHashPartitions(hashKeys, numBuckets); try { if(!client.tableExists(tableName)) { client.createTable(tableName, schema, createTableOptions); } System.out.println("成功創建Kudu表:" + tableName); } catch (KuduException e) { e.printStackTrace(); } } /** * 向指定的Kudu表中upsert數據,數據存在則更新,不存在則新增 * @param client KuduClient對象 * @param tableName 表名 * @param numRows 向表中插入的數據量 */ public static void upsert(KuduClient client, String tableName, int numRows ) { try { KuduTable kuduTable = client.openTable(tableName); KuduSession kuduSession = client.newSession(); //設置Kudu提交數據方式,這裏設置的爲手動刷新,默認爲自動提交 … kuduSession.flush(); kuduSession.close(); } catch (KuduException e) { e.printStackTrace(); } } /** * 查看Kudu表中數據 * @param client * @param tableName */ public static void scanerTable(KuduClient client, String tableName) { try { KuduTable kuduTable = client.openTable(tableName); KuduScanner kuduScanner = client.newScannerBuilder(kuduTable).build(); while(kuduScanner.hasMoreRows()) { RowResultIterator rowResultIterator =kuduScanner.nextRows(); while (rowResultIterator.hasNext()) { RowResult rowResult = rowResultIterator.next(); System.out.println(rowResult.getString("id")); } } kuduScanner.close(); } catch (KuduException e) { e.printStackTrace(); } } /** * 刪除表 * @param client * @param tableName */ public static void dropTable(KuduClient client, String tableName) { try { client.deleteTable(tableName); } catch (KuduException e) { e.printStackTrace(); } } /** * 列出Kudu下所有的表 * @param client */ public static void tableList(KuduClient client) { try { ListTablesResponse listTablesResponse = client.getTablesList(); List<String> tblist = listTablesResponse.getTablesList(); for(String tableName : tblist) { System.out.println(tableName); } } catch (KuduException e) { e.printStackTrace(); } } }
(可左右滑動)
4
示例代碼及運行
1.KuduKerberosExample爲測試類包含API的調用
package com.cloudera; import com.cloudera.utils.ClientUtils; import com.cloudera.utils.KuduUtils; import org.apache.hadoop.security.UserGroupInformation; import org.apache.kudu.client.KuduClient; import org.apache.kudu.client.KuduException; import java.io.IOException; import java.security.PrivilegedExceptionAction; /** * package: com.cloudera * describe: 訪問Kerberos環境下的Kudu * creat_user: Fayson * email: [email protected] * creat_date: 2018/11/15 * creat_time: 上午12:32 * 公衆號:Hadoop實操 */ public class KuduKerberosExample { public static void main(String[] args) { ClientUtils.initKerberosENV(false); String kudu_master = System.getProperty("kuduMasters", "cdh1.fayson.com:7051,cdh2.fayson.com:7051,cdh3.fayson.com:7051"); try { KuduClient kuduClient = UserGroupInformation.getLoginUser().doAs( new PrivilegedExceptionAction<KuduClient>() { @Override public KuduClient run() throws Exception { return new KuduClient.KuduClientBuilder(kudu_master).build(); } } ); String tableName = "user_info_kudu"; //刪除Kudu的表 KuduUtils.dropTable(kuduClient, tableName); //創建一個Kudu的表 KuduUtils.createTable(kuduClient, tableName); //列出Kudu下所有的表 KuduUtils.tableList(kuduClient); //向Kudu指定的表中插入數據 KuduUtils.upsert(kuduClient, tableName, 100); //掃描Kudu表中數據 KuduUtils.scanerTable(kuduClient, tableName); try { kuduClient.close(); } catch (KuduException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }
(可左右滑動)
2.示例運行
3.訪問Kudu Master的UI界面
點擊“Table Id”進入user_info_kudu表詳細頁面
使用Kudu表提供的Impala建表語句,在Impala上創建外部表
CREATE EXTERNAL TABLE `user_info_kudu` STORED AS KUDU TBLPROPERTIES( 'kudu.table_name' = 'user_info_kudu', 'kudu.master_addresses' = 'cdh1.fayson.com:7051,cdh2.fayson.com:7051,cdh3.fayson.com:7051')
(可左右滑動)
查詢user_info_kudu表數據
5
總結
1.在進行本地開發時,必須將集羣的hostname及IP配置在本地的hosts文件中(如果使用DNS服務則可以不配置hosts文件),否則無法與集羣互通,確保本地客戶端與集羣的端口是放通的。
2.訪問Kerberos環境下的Kudu時,需要使用HDFS API提供的UserGroupInformation類實現Kerberos賬號登錄認證,該API在登錄Kerberos認證後,會啓動一個線程定時的刷新認證。
GitHub源碼地址:
https://github.com/fayson/cdhproject/blob/master/kududemo/src/main/java/com/cloudera/KuduKerberosExample.java
https://github.com/fayson/cdhproject/blob/master/kududemo/src/main/java/com/cloudera/utils/ClientUtils.java
https://github.com/fayson/cdhproject/blob/master/kududemo/src/main/java/com/cloudera/utils/KuduUtils.java
提示:代碼塊部分可以左右滑動查看噢
爲天地立心,爲生民立命,爲往聖繼絕學,爲萬世開太平。 溫馨提示:如果使用電腦查看圖片不清晰,可以使用手機打開文章單擊文中的圖片放大查看高清原圖。
推薦關注Hadoop實操,第一時間,分享更多Hadoop乾貨,歡迎轉發和分享。