我们这边是通过hive-jdbc,druid连接池连接hiveserver2查询hive数据,但每次hiveserver2重启后,查询程序也得重启,不然会重复使用已经无效的连接,提交的查询报错
java.lang.Exception: ERROR:org.apache.thrift.transport.TTransportException: java.net.SocketException: Broken pipe
查询DruidDataSourceFactory.createDataSource源码,发现创建连接时,super(fairLock)中给定了一些固定配置,
public DruidAbstractDataSource(boolean lockFair) {
this.validationQuery = DEFAULT_VALIDATION_QUERY;
this.validationQueryTimeout = -1;
this.testOnBorrow = false;
this.testOnReturn = false;
this.testWhileIdle = true;
this.testWhileIdle = true;
……
}
通过官方文档查询相关参数含义
配置 | 缺省值 | 说明 |
---|---|---|
validationQuery | 用来检测连接是否有效的sql,要求是一个查询语句,常用select ‘x’。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 | |
validationQueryTimeout | 单位:秒,检测连接是否有效的超时时间。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法 | |
testOnBorrowtrue | true | 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 |
testOnReturnfalse | false | 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 |
testWhileIdle | false | 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 |
DEFAULT_VALIDATION_QUERY的值为null,即使testWhileIdle配置了true也无效,druid连接池进行dataSource.init()的时候会根据jdbc类型inti一个ValidConnectionChecker进行连接验证,hive-jdbc没有ValidConnectionChecker
this.initValidConnectionChecker();
this.validationQueryCheck();
private void initValidConnectionChecker() {
if (this.validConnectionChecker == null) {
String realDriverClassName = this.driver.getClass().getName();
if (JdbcUtils.isMySqlDriver(realDriverClassName)) {
this.validConnectionChecker = new MySqlValidConnectionChecker();
} else if (!realDriverClassName.equals("oracle.jdbc.OracleDriver") && !realDriverClassName.equals("oracle.jdbc.driver.OracleDriver")) {
if (!realDriverClassName.equals("com.microsoft.jdbc.sqlserver.SQLServerDriver") && !realDriverClassName.equals("com.microsoft.sqlserver.jdbc.SQLServerDriver") && !realDriverClassName.equals("net.sourceforge.jtds.jdbc.Driver")) {
if (realDriverClassName.equals("org.postgresql.Driver") || realDriverClassName.equals("com.edb.Driver")) {
this.validConnectionChecker = new PGValidConnectionChecker();
}
} else {
this.validConnectionChecker = new MSSQLValidConnectionChecker();
}
} else {
this.validConnectionChecker = new OracleValidConnectionChecker();
}
}
}
private void validationQueryCheck() {
if (this.testOnBorrow || this.testOnReturn || this.testWhileIdle) {
if (this.validConnectionChecker == null) {
if (this.validationQuery == null || this.validationQuery.length() <= 0) {
String errorMessage = "";
if (this.testOnBorrow) {
errorMessage = errorMessage + "testOnBorrow is true, ";
}
if (this.testOnReturn) {
errorMessage = errorMessage + "testOnReturn is true, ";
}
if (this.testWhileIdle) {
errorMessage = errorMessage + "testWhileIdle is true, ";
}
LOG.error(errorMessage + "validationQuery not set");
}
}
}
}
为解决问题我们自己赋值validationQuery,在hive-jdbc中select 1查询性能比show databases慢很多,为了提高validationQuery查询性能我们使用show databases,为了减少返回数据数量,使用show databases LIKE 'DB_NAME’语句(自己的库名称),测试与show databases查询性能相近。
补充:
hive-jdbc不支持validationQueryTimeout参数,会报Method not supported的异常