使用连接池导致metastore连接被打满

现象:

GenericObjetPool 配置的5个连接,为什么会创建这么多连接? 看日志在不断的在init和close连接

先看下连接池配置参数

maxActive                     最大活跃连接数
 maxIdle                       链接池中最大空闲的连接数
 minIdle                       连接池中最少空闲的连接数
 maxWait                       当连接池资源耗尽时,调用者最大阻塞的时间
 timeBetweenEvictionRunsMillis 空闲链接检测线程,检测的周期,毫秒数,-1 表示关闭空闲检测
 minEvictableIdleTimeMillis    空闲链接超过时间后被销毁,-1 表示不检查空闲时间
 testWhileIdle                 空闲时是否进行连接有效性验证,如果验证失败则移除,默认为 true
 testOnBorrow                  判断这条连接是否是可用
 testOnReturn                  连接池回收连接的时候会判断该连接是否还可用

关键在 minEvictableIdleTimeMillis 这个参数,空闲连接时长,默认30分钟,timeBetweenEvictionRunsMillis 配置的5s,就是每隔5s检测连接的有效性和空闲时间,如果空闲时间超过三十分钟,就会调用 destroyObject 方法,关闭连接,从连接池中移除

minIdle 连接池中最少的空闲链接数,配置的是5个,destory一个,在重新 init 一个加到池子里,所以会反复的 close,init

但是为啥调用了 destroyObject 方法,链接没有关闭?

public void destroyObject(ThriftHiveMetastore.Client client) {
    logger.info("close metastore client");
    try {
        client.shutdown();
    } catch (TException e) {
        logger.error("关闭连接失败!", e);
    }
}

看下 client.shutdown() 方法,最后执行的是

pm 就是 PersistenceManager

只是关闭了数据库的连接

而client初始化方式是

public ThriftHiveMetastore.Client makeObject() throws Exception {
    logger.info("init metastore client");
    for (String host: hosts) {
        TTransport transport = new TSocket(host, port);
        TProtocol protocol = new TBinaryProtocol(transport);
        ThriftHiveMetastore.Client client = new ThriftHiveMetastore.Client(protocol);
        transport.open();
        return client;
    }
    return null;
}

没有关闭底层的 TSocket,连接没有真正关闭,所以会导致连接数不断增多

修改关闭连接的方法,参考了 HiveMetaStoreClient.close() 方法

public void destroyObject(ThriftHiveMetastore.Client client) {
    logger.info("close metastore client");
    try {
        client.shutdown();
    } catch (TException e) {
        logger.error("关闭连接失败!", e);
    }
 
    try {
        //HiveMetaStoreClient.close() 方法
        // Transport would have got closed via client.shutdown(), so we dont need this, but
        // just in case, we make this call.
        TTransport transport = client.getOutputProtocol().getTransport();
        if ((transport != null) && transport.isOpen()) {
            transport.close();
            logger.info("Closed connection to metastore");
        }
    } catch (Exception e) {
        logger.error("transport close error!", e);
    }
}

HiveMetaStoreClient.close() 方法

为啥没直接用封装好的 HiveMetaStoreClient?原因:https://issues.apache.org/jira/browse/HIVE-23700

测试:连接池配置空闲的连接数为 1 个

在 hivedev01.dev 这台机器上看当前的连接数

netstat -na |grep 9083|grep -v LISTEN | wc -l

修改close方法前,运行一段时间

修改close方法后,运行一段时间

修改后连接数没有一直增加,问题修复

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦