kerberos認證+impala-jdbc驅動+鏈接池,集成到spring框架

1 兩種jbdc驅動,kerberos認證的區別描述

1-1 hive-jdbc驅動與kerberos認證  

  對於hive-jdbc驅動,kerberos認證的代碼塊與Connection實例化的代碼塊,耦合性不強,保證執行的時序性便可。(kerberos認證在前,Connection實例化在後),以下圖所示。php

圖片描述

代碼以下。html

// 先執行kerberos認證的代碼塊
    // 1. login use keytab
    System.setProperty("java.security.krb5.realm", "XXX.COM");
    System.setProperty("java.security.krb5.kdc", "kdcXXX");
    Configuration conf = new Configuration();
    conf.set("hadoop.security.authentication", "Kerberos");
    UserGroupInformation.setConfiguration(conf);
    UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("test", "test.keytab");

    // 接着執行Connection實例化的代碼塊
    try {  
        Class.forName(driverName);  
        
        Connection conn = DriverManager.getConnection(url);  
        Statement stmt = conn.createStatement();  
        String sql = "show databases;";  
        ResultSet rs = stmt.executeQuery(sql);  
        while(rs.next()){  
            System.out.println(rs.getString(1));  
        }  
    } catch (Exception e) {  
        e.printStackTrace();  
    }

1-2 impala-jdbc驅動與kerberos認證

  對於impala-jdbc驅動,kerberos認證的代碼塊與Connection實例化的代碼塊,二者強耦合,除了保證執行的時序性(kerberos認證在前,Connection實例化在後),還要求在doAs函數,建立Connection,以下圖所示。
  
圖片描述java

  代碼以下所示。spring

// kerberos認證的代碼塊
    // 1. login use keytab
    System.setProperty("java.security.krb5.realm", "XXX.COM");
    System.setProperty("java.security.krb5.kdc", "kdcXXX");
    Configuration conf = new Configuration();
    conf.set("hadoop.security.authentication", "Kerberos");
    UserGroupInformation.setConfiguration(conf);
    UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("test", "test.keytab");

    // 在UserGroupInformation的doAs函數中實現Connection的建立
    // 2. create impala jdbc connection
    Class.forName(JDBCDriverName);
    conn = (Connection) ugi.doAs(new PrivilegedExceptionAction<Object>() {
      public Object run() {
        Connection tcon = null;
        try {
          tcon = DriverManager.getConnection(connectionUrl);
        } catch (SQLException e) {
          e.printStackTrace();
        }
        return tcon;
      }
    });

    // 3. execute query using conn

2 kerberos認證與鏈接池集成方案

  對比上述兩段代碼,當引入鏈接池技術來管理Connection時。對不一樣驅動分別說明之。sql

2-1 hive-jdbc,kerberos認證與鏈接池集成方案

  對hive-jdbc狀況,比較簡單,知足兩個代碼塊執行的時序性便可。即確保在鏈接池實例化前,執行kerberbos認證的代碼塊。具體實現方法:① spring bean中的depends-on標籤(見參考文獻[3])。② 配置Listener。見參考文獻[2])。
  這種狀況,不是本文章的重點,這裏不對它具體展開。數據庫

2-2 impala-jdbc,kerberos認證與鏈接池集成方案

  考慮到Connection建立是鏈接池類內部的函數。而kerberos認證代碼塊是對Connection建立這一過程自己進行包裹。即kerberos認證的代碼塊,與鏈接池類內部的函數建立Connection的代碼塊,二者強耦合。以下圖所示。
  
圖片描述windows

  考慮到上述狀況,如何打開鏈接池類的封裝,對鏈接池類內部的getConnection函數加上kerberbos認證的邏輯?
  換言之,對如何對一個類的方法進行加強?
  最樸素的路子是繼承這個類,而後覆寫這個類中的目標加強方法。
  以Druid鏈接池爲例,建立一個類繼承DruidSource,對全部getConnection相關的幾個函數重寫,把kerberbos認證相關的代碼塊嵌入到該函數裏面。這樣能夠經過kerberbos認證,並返回Connection。mvc

public class DruidDataSourceWrapper extends DruidDataSource {

    // 建立一個函數,指向父類的getConnection(long)方法
    public DruidPooledConnection superGetConnection(long maxWaitMillis) throws SQLException {
        return super.getConnection(maxWaitMillis);
    }
    
    /**
     * 覆寫父類的getConnection(long)方法,在父類的getConnection(long)方法外面包裹上kerberbos認證的代碼塊
     */
    @Override
    public DruidPooledConnection getConnection(final long maxWaitMillis) throws SQLException {

        // kerberos認證的代碼塊
        // 1. login use keytab
        System.setProperty("java.security.krb5.realm", "XXX.COM");
        System.setProperty("java.security.krb5.kdc", "kdcXXX");
        Configuration conf = new Configuration();
        conf.set("hadoop.security.authentication", "Kerberos");
        UserGroupInformation.setConfiguration(conf);
        UserGroupInformation ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("test", "test.keytab");

        // 在UserGroupInformation的doAs函數中實現Connection的建立
        // 覆寫父類的getConnection(long)方法,在方法外面包裹上kerberbos認證的代碼塊
        DruidDataSourceWrapper _this = this;
        Connection conn = ugi.doAs(new PrivilegedExceptionAction<Connection>() {
          public Connection run() {
            Connection tcon = null;
            try {
                // 父類的getConnection(long)方法
                tcon = _this.superGetConnection(maxWaitMillis);    
            } catch (SQLException e) {
              e.printStackTrace();
            }
            return tcon;
          }
        });
        
        // 返回connection
        return conn;
    }    
}

  在與spring框架集成時,在鏈接池相關的xml配置文件中,關於數據庫鏈接池,class類路徑指向咱們封裝的類路徑便可。app

<bean id="dataSource" class="com.tools.pool.DruidDataSourceWrapper">
    <property name="driverClassName" value="com.cloudera.impala.jdbc41.Driver"/>
    <property name="url" value="your_url"/>
    <property name="username" value="your_username"/>
    <property name="password" value="your_password"/>
</bean>

2-3集成方案中可能存在的技術點

  上述涉及到對一個類的函數功能進行加強,有點鏈接池類被final修飾,不能被繼承。有沒有其它的方法對不能繼承的類進行加強呢?答案是存在的,是裝飾者模式與動態代理模式。
  舉個例子:c3p0鏈接池,比較適合裝飾者模式對getConnection函數進行加強。
  對於Java中加強一個類的幾種方法,具體參考文獻[6]、[7]。框架

3 參考文獻

[1] https://blog.csdn.net/tlqfree... (windows環境 java jdbc 鏈接impala (kerberos認證) - 空谷幽蘭草堂 - CSDN博客)
[2] https://blog.csdn.net/zhanglu... (springmvc集成kerberos認證hive jdbc鏈接 - 張小竟 - CSDN博客)
[3] http://www.aboutyun.com/forum... (hive + kerberos spring 配置 DruidDataSource 數據庫鏈接池-Hive-about雲開發)
[4] https://www.cnblogs.com/zhish... (Spring depends-on介紹)
[5] https://stackoverflow.com/que... (authentication - Error when connect to impala with JDBC under kerberos authrication - Stack Overflow)
[6] https://blog.csdn.net/friday_... (Java中加強一個類的幾種方法 - friday_PJ的博客 - CSDN博客)
[7] https://www.cnblogs.com/xuzha... (對java方法進行功能加強的三種方法)

4 結束語

  若是個人技術博客節約了你們的寶貴的時間,歡迎你們請我喝杯茶,^V^。

相關文章
相關標籤/搜索