一、 各组件简介:
Mybatis-plus 基于轻量级持久层框架mybatis的增强,易于使用,支持lamda方式查询、多数据源动态配置等;
HikariCP目前流行的数据库链接池,springboot2.0默认使用;
Impala是Cloudera公司主导开发的新型查询系统,它提供SQL语义,能查询存储在Hadoop的HDFS和HBase中的PB级大数据。
Kerberos是一种计算机网络认证协议,他能够为网络中通信的双方提供严格的身份验证服务,确保通信双方身份的真实性和安全性
二、存在问题
项目为已部署项目, impala新增Kerberos认证,因原有项目架构体系, 引入了多数据源, 新增认证只针对impala链接的升级,需要适配当前框架增加Kerberos客户端用户验证
三、解决思路
思路一: 做切面, 每次获取connection时做增强方法
思路二: 重写连接池getConnection方法, 将自定义连接池整合入mybatis-plus动态数据源框架
本文主要采用思路二,重写了数据连接池
二、主要步骤如下
pom文件引入
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.10.0</version> </dependency>
1、Impala Kerberos身份验证
验证配置是否正确,数据链路是否打通, 如果存在问题, 请依据服务端配置调整参数。
public static void main(String[] args){
// kerberos认证的代码块
// 1. login use
Configuration conf = initConfiguration();
System.setProperty("java.security.krb5.conf", "/../krb5.conf");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("java.security.auth.login.config","/../jaas.conf");
String keyPath = "/../user.keytab";
try {
UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab("name", keyPath);
UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
Connection conn = loginUser.doAs(new PrivilegedExceptionAction<Connection>() {
public Connection run() {
Connection tcon = null;
try {
// 父类的getConnection(long)方法
Class.forName("com.cloudera.impala.jdbc41.Driver");
Connection connection = DriverManager.getConnection("jdbc:impala://host:port/dbname;AuthMech=1;KrbRealm=XXXX;KrbHostFQDN=host;KrbServiceName=impala");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select count(1) from users");
System.out.println(resultSet);
log.info("resultSet: "+resultSet);
} catch (Exception e) {
log.error("获取数据源链接失败",e);
}
return tcon;
}
});
} catch (Exception e){
log.error("获取数据源链接失败..",e);
}
return "";
}
2 重写HikariCP数据连接池 getConnection方法
继承HikariDataSource 重写getConnection方法,在获取链接时做认证操作
public class DataSourceConfig extends HikariDataSource{
// 创建一个函数,指向父类的getConnection(long)方法
public Connection superGetConnection() throws SQLException {
return super.getConnection();
}
@Override
public Connection getConnection() throws SQLException{
// kerberos认证的代码块
// 1. login use
Configuration conf = initConfiguration();
System.setProperty("java.security.krb5.conf", "/../krb5.conf");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("java.security.auth.login.config","/../jaas.conf");
String keyPath = "/../user.keytab";
try {
UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab("name", keyPath);
UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
Connection conn = loginUser.doAs(new PrivilegedExceptionAction<Connection>() {
public Connection run() {
Connection tcon = null;
try {
// 父类的getConnection(long)方法
Class.forName("com.cloudera.impala.jdbc41.Driver");
tcon = DriverManager.getConnection("jdbc:impala://host:port/dbname;AuthMech=1;KrbRealm=XXXX;KrbHostFQDN=host;KrbServiceName=impala");
} catch (Exception e) {
log.error("获取数据源链接失败",e);
}
return tcon;
}
});
} catch (Exception e){
log.error("获取数据源链接失败..",e);
}
return null;
}
}
3 注册当前连接池到mybatis-plus动态数据源
dataSourceProperties.setDriverClassName(kerberoProperties.getDriverClassName());
dataSourceProperties.setUrl(kerberoProperties.getUrl());
dataSourceProperties.setUsername(kerberoProperties.getUsername());
dataSourceProperties.setPassword(kerberoProperties.getPassword());
//创建自定义数据连接池
DataSourceConfig targetDataSource = dataSourceProperties.initializeDataSourceBuilder().type(DataSourceConfig.class).build();
if (StringUtils.hasText(dataSourceProperties.getName())) {
targetDataSource.setPoolName(dataSourceProperties.getName());
}
targetDataSource.setMaxLifetime(0);//设置最长生命周期为无限长,https://www.jianshu.com/p/fa9e0bff4cd9/
//获取动态数据源
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
//包装自定义数据连接池
ItemDataSource itemDataSource = new ItemDataSource(kerberoProperties.getId(),targetDataSource,targetDataSource,false,false, SeataMode.AT);
//添加自定义数据连接池
ds.addDataSource(kerberoProperties.getId(), itemDataSource);
参考文章:
1、基于mybatis plus实现数据源动态添加、删除、切换,自定义数据源的示例代码
2、kerberos+druid+impala_laolvbig的博客-CSDN博客
3、Simba Impala JDBC Driver with SQL Connector