java jdbc連接impala (集成Kerberos)

有這樣的一個業(yè)務場景-客戶端通過接口訪問impala Daemon叨吮,impala做查詢并返回數(shù)據(jù)給到客戶端锋玲;
下面通過impala jdbc訪問服務方式來介紹客戶端調(diào)用接口訪問impala場景
訪問實例前惭蹂,會做kerberos認證; 通過后就允許訪問相關(guān)服務
在實施方案前盾碗,假設讀者已經(jīng)基本熟悉以下技術(shù) (不細說)
  • Java廷雅,maven
  • impala榜轿, hdfs谬盐,kerberos
方案實施
  • 把kdc服務端krb5.conf拷貝到本地工程目錄
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = WONHIGH.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true

[realms]
 WONHIGH.COM = {
 #注意這里最好改成IP飞傀,因為你部署工程的機器有可能并不知道host對應的ip
  kdc = 172.17.194.20
  admin_server = 172.17.194.20
 }

  • 生成的keytab文件并拷貝都工程目錄下
kadmin.local:  xst -norandkey -k wms_dev.keytab wms_dev@WONHIGH.COM 
  • 工程目錄


    keytab_krb5.png
  • 然后就是代碼了,不多說幢痘,直接上 (頭暈的直接拉到最下面看效果即可)
  • pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>deng.yb</groupId>
  <artifactId>impalaJdbc</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>impalaJdbc</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <hive.version>2.5.42</hive.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    
    <dependency>
      <groupId>com.cloudera</groupId>
      <artifactId>impala-jdbc41</artifactId>
      <version>${hive.version}</version>
    </dependency>
       <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.44</version>
    </dependency>
    <dependency>
           <groupId>org.apache.hadoop</groupId>
           <artifactId>hadoop-client</artifactId>
           <version>2.6.5</version>
       </dependency>
       <dependency>
           <groupId>org.apache.hive</groupId>
           <artifactId>hive-jdbc</artifactId>
           <version>1.1.0</version>
    </dependency>
  </dependencies>
</project>\
  • 主類
package impala.kerberos;

import impala.conf.KbsConfiguration;
import impala.kerberos.callback.CallBack;
import impala.utils.Tools;

import java.io.IOException;
import java.security.PrivilegedAction;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;

import org.apache.hadoop.security.UserGroupInformation;

public class KBImpalaJBDC {
    private static String JDBC_DRIVER = "com.cloudera.impala.jdbc41.Driver";
    private static String CONNECTION_URL = "jdbc:impala://{0}:21050/;AuthMech=1;KrbRealm={1};KrbHostFQDN={0};KrbServiceName=impala";
    private static String SECURITY_KRB5_CONF = "java.security.krb5.conf";
    private static String HADOOP_SECURITY_AUTH = "hadoop.security.authentication";
    private static String DEFAULT_REALM = "WONHIGH.COM";
    
    
    private String user;
    private String realm;
    private String krb5ConfDest = "krb5.conf";
    private String keytabDest;

    static {
        try {
            Class.forName(JDBC_DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public KBImpalaJBDC(String deamonHost, String realm) {
        this.realm = realm;
        CONNECTION_URL = MessageFormat
                .format(CONNECTION_URL, deamonHost, realm);
    }

    public KBImpalaJBDC(String deamonHost) {
        this(deamonHost, DEFAULT_REALM);
    }

    public KBImpalaJBDC user(String user) {
        this.user = user;
        return self();
    }
    
    public KBImpalaJBDC krb5Dest(String krb5ConfDest) {
        this.krb5ConfDest = krb5ConfDest;
        return self();
    }
    
    public KBImpalaJBDC keytabDest(String keytabDest) {
        this.keytabDest = keytabDest;
        return self();
    }
    
    public Object runWithKrbs(final String sql,final CallBack func) {
        if (null == user || user.length() == 0) {
            throw new RuntimeException("用戶不能為空!");
        }

        System.out.println("通過JDBC連接訪問Kerberos環(huán)境下的Impala");
        // 登錄Kerberos賬號
        try {

            System.setProperty(SECURITY_KRB5_CONF,
                    Tools.getPath(krb5ConfDest));
            
            UserGroupInformation.setConfiguration(KbsConfiguration
                    .newInstance().setPro(HADOOP_SECURITY_AUTH,
                            "Kerberos"));

            UserGroupInformation.loginUserFromKeytab(
                    user,
                    Tools.getPath(keytabDest == null?(user.replace(realm, "") + ".keytab"):keytabDest));
            
            UserGroupInformation logUser = UserGroupInformation.getLoginUser();
            
            if (null == logUser) {
                throw new RuntimeException("登錄用戶為空!");
            }
            System.out.println(UserGroupInformation.getCurrentUser() + "------"
                    + logUser );

            return logUser.doAs(new PrivilegedAction<Object>() {
                public Object run() {
                    Connection connection = null;
                    ResultSet rs = null;
                    PreparedStatement ps = null;
                    try {

                        //Class.forName(JDBC_DRIVER);
                        connection = DriverManager
                        .getConnection(CONNECTION_URL);
                        ps = connection.prepareStatement(sql);
                        rs = ps.executeQuery();
                        
                        if (null == func) {
                            
                            return null;
                            
                        } else {
                            
                            return func.deal(rs);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (connection != null) {
                                connection.close();
                            }
                            if (ps != null) {
                                ps.close();
                            }
                            if (rs != null) {
                                rs.close();
                            }
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                    }
                    return null;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    private KBImpalaJBDC self() {
        return this;
    }
}

  • 工具類
package impala.utils;

public class Tools {
    
    public static String getPath(String fileName) {
        if (null == fileName || fileName.length() == 0) {
            throw null;
        }

        return currentLoader().getResource(fileName).getPath();
    }

    public static ClassLoader currentLoader() {
        return Thread.currentThread().getContextClassLoader();
    }
}
  • 輔助類和接口
package impala.conf;

import org.apache.hadoop.conf.Configuration;

public class KbsConfiguration extends Configuration {

    public static KbsConfiguration newInstance() {
        return new KbsConfiguration();
    }

    public Configuration setPro(String name, String value) {
        super.set(name, value);
        return this;
    }
    
}

package impala.kerberos.callback;

public interface CallBack {
     Object deal (Object obj);
}

方案驗證
  • 測試類
package impalaJdbc.testCase;

import impala.kerberos.KBImpalaJBDC;
import impala.kerberos.callback.CallBack;

import java.sql.ResultSet;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        KBImpalaJBDC jdbc = new KBImpalaJBDC("bi-slave1");
        Object obj  =   jdbc.user("wms_dev@WONHIGH.COM")
                            .krb5Dest("krb5.conf")
                            .keytabDest("wms_dev.keytab")
                            .runWithKrbs("select count(1) from gtp.ods_item;",new CallBack(){
                                public Object deal(Object obj) {
                                    try {
                                        
                                        if (obj instanceof ResultSet) {
                                            ResultSet result = (ResultSet) obj;
                                            StringBuilder builder = new StringBuilder();
                                            while (result.next()) {
                                                builder.append(result.getString(1)+"\n");
                                            }
                                            
                                            return builder.toString();
                                        }
                                        
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    
                                    return null;
                                }
                            });
        
        System.out.println((obj!=null && obj instanceof java.lang.String)?obj.toString():"");
        
    }
}

  • 代碼結(jié)果


    代碼結(jié)果.png
  • 直接登陸服務查詢結(jié)果


    impala_服務結(jié)果.png
  • 結(jié)果一致!

遺留問題
  • 有經(jīng)驗的開發(fā)會發(fā)現(xiàn)一個問題绎签;就是代碼里面寫死訪問同一個impala實例酝锅,并發(fā)量一大會不會導致impala Daemon服務罷工屈张。答案是肯定的阁谆!
  • 解決思路:實現(xiàn)軟均衡負載场绿,
  • 具體方案;在客戶端與服務端直接搭建 HAProxy服務璧尸, 監(jiān)聽相應接口爷光,分發(fā)請求蛀序;以下是通過HAProxy實現(xiàn)impala均衡負載方案

均衡方案實施前徐裸,假設滿足以下條件

  • impala服務正常
  • 集成kerberos正常
HAProxy安裝和配置
yum -y install haproxy
  • 啟動與停止HAProxy服務
service haproxy start
service haproxy stop
chkconfig haproxy on
  • 配置Impala負載均衡
mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
vi /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Example configuration for a possible web application.  See the
# full configuration options online.
#
#   http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    #option http-server-close
    #option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000


listen stats
    bind 0.0.0.0:1080
    mode http
    option httplog
    maxconn 5000
    stats refresh 30s
    stats  uri /stats

listen impalashell
    bind 0.0.0.0:25003
    mode tcp
    option tcplog
    balance leastconn
    server bi-slave1 bi-slave1:21000 check
    server bi-slave2 bi-slave2:21000 check
    server bi-slave3 bi-slave3:21000 check

listen impalajdbc
    bind 0.0.0.0:25004
    mode tcp
    option tcplog
    balance leastconn
    server bi-slave1 bi-slave1:21050 check
    server bi-slave2 bi-slave2:21050 check
    server bi-slave3 bi-slave3:21050 check

  • 啟動HAProxy服務
service haproxy restart
  • 查看是否啟動正常


    haproxy_stats.png
impala 配置
load_balance.png
  • 保存重啟
Impala Shell測試
  • 打開兩個窗口气笙,同時訪問impala-shell -i bi-master:25003


    企業(yè)微信截圖_15284393253991.png

    企業(yè)微信截圖_15284393378471.png
  • 發(fā)現(xiàn)請求會分發(fā)到不同impala daemon上健民,證明均衡負載配置成功
  • 同理:java jdbc連接把Connect url的節(jié)點改為bi-master:25004即可
hue配置
  • impala均衡負載配置后,進入impala查詢會有可能報以下錯


    企業(yè)微信截圖_15284412421912.png
  • 解決辦法稚晚,在hue配置中修改


    hue_safety_value.png
  • 重啟hue服務即可
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸳劳,一起剝皮案震驚了整個濱河市赏廓,隨后出現(xiàn)的幾起案子幔摸,更是在濱河造成了極大的恐慌颤练,老刑警劉巖嗦玖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宇挫,死亡現(xiàn)場離奇詭異,居然都是意外死亡又谋,警方通過查閱死者的電腦和手機彰亥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門任斋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來废酷,“玉大人澈蟆,你說我怎么就攤上這事卓研。” “怎么了寥闪?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵凿渊,是天一觀的道長缚柳。 經(jīng)常有香客問我,道長剂癌,這世上最難降的妖魔是什么翰绊? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任谐檀,我火速辦了婚禮裁奇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘溃肪。我一直安慰自己惫撰,他們只是感情好厨钻,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布夯膀。 她就那樣靜靜地躺著苍蔬,像睡著了一般碟绑。 火紅的嫁衣襯著肌膚如雪茎匠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天伯病,我揣著相機與錄音午笛,去河邊找鬼药磺。 笑死煤伟,一個胖子當著我的面吹牛便锨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播姚建,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼掸冤,長吁一口氣:“原來是場噩夢啊……” “哼友雳!你這毒婦竟也來了押赊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤策精,失蹤者是張志新(化名)和其女友劉穎咽袜,沒想到半個月后枕稀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谜嫉,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡沐兰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年住闯,在試婚紗的時候發(fā)現(xiàn)自己被綠了比原。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杠巡。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡氢拥,死狀恐怖嫩海,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情出革,我是刑警寧澤骂束,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布展箱,位于F島的核電站,受9級特大地震影響攀隔,放射性物質(zhì)發(fā)生泄漏栖榨。R本人自食惡果不足惜婴栽,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望映皆。 院中可真熱鬧,春花似錦组去、人聲如沸从隆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽韧衣。三九已至,卻和暖如春氏淑,著一層夾襖步出監(jiān)牢的瞬間硕噩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谍失,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓颠印,卻偏偏與公主長得像抹竹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子闻坚,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容