总结
连接池关系
1、HikariDataSource构建函数->生成HikariPool对象->调用HikariPool的getConection得到连接
2、HikariPool包含ConcurrentBag
3、ConcurrentBag保存连接:三个集合threadList、sharedList、handoffQueue
4、ConcurrentBag管理连接:创建连接的线程池,探活的线程池,关闭连接的线程池、阻塞队列
5、探活的线程池:调用关闭连接的线程池,调用创建链接的线程池。
6、连接Connection被包装成了poolEntry,通过poolEntryCreator->得到poolEntry->添加到shareList里面去。
7、释放链接:判断是否人等待获取链接的请求,如果有塞到handoffQueue,如果没有添加到自己线程的threadList里面去。
数据库连接池主要分为两大内容
1、连接的获取,主要涉及三个容器: threadList、sharedList、handoffQueue
2、连接池的管理:主要包含连接的创建,连接的定期检测,是否有效是否空闲,连接的关闭

源码分析
HikariDataSource常用的参数配置
connectionTimeou:客户端创建连接等待超时时间,如果30秒内没有获取连接则抛异常,不再继续等待
idleTimeout:连接允许最长空闲时间,如果连接空闲时间超过1分钟,则会被关闭
maxLifetime:连接最长生命周期,当连接存活时间达到30分钟之后会被关闭作退休处理
minimumIdle:连接池中最小空闲连接数
maximumPoolSize:连接池中最大连接数
validationTimeout:测试连接是否空闲的间隔
leadDetectionThreshold:连接被占用的超时时间,超过1分钟客户端没有释放连接则强制回收该连接,防止连接泄漏
1、HikariPool
Hikari中的核心类为HikariDataSource,表示Hikari连接池中的数据源,实现了DataSource接口的getConnection方法,获取链接主要是为了拿到Connection,而拿到Connection就是要通过HikariPool的实例对象来获取。
所以在HikariDataSource的构造函数里面会创建HikariPool对象。为了在调用getConnection方法时,从HikariPool里面拿到Connection
private final HikariPool fastPathPool;
private volatile HikariPool pool;
public HikariDataSource(HikariConfig configuration){
pool = fastPathPool = new HikariPool(this);
}
/** 获取连接*/
public Connection getConnection() throws SQLException{
if (fastPathPool != null) {
return fastPathPool.getConnection();
}
pool = result = new HikariPool(this);
/** 调用pool的getConnection()方法获取连接*/
return result.getConnection();
}
小结:HikariDataSource->生成HikariPool对象->HikariPool对象得到Connection。
重点看HikariPool的getConnection()方法逻辑时如何得到connection
/** 获取连接*/
public Connection getConnection(final long hardTimeout) throws SQLException{
/** 获取锁*/
suspendResumeLock.acquire();
try {
do {
/** 1、从ConcurrentBag中借出一个PoolEntry对象 */
PoolEntry poolEntry = connectionBag.borrow(timeout, MILLISECONDS);
if (poolEntry == null) {
break;
}
/** 判断连接是否被标记为抛弃 或者 空闲时间过长, 是的话就关闭连接*/
if (......) {
closeConnection(poolEntry, poolEntry.isMarkedEvicted() ? EVICTED_CONNECTION_MESSAGE : DEAD_CONNECTION_MESSAGE);
}
/** 2、拿到poolEntry,通过Javassist创建代理连接*/
return poolEntry.createProxyConnection(leakTaskFactory.schedule(poolEntry), now);
} while (timeout > 0L);
throw createTimeoutException(startTime);
} finally {
/** 释放锁*/
suspendResumeLock.release();
}
}
核心步骤只有两步,一个是调用ConcurrentBag的borrow方法借用一个PoolEntry对象,第二步调用调用PoolEntry的createProxyConnection方法动态生成代理connection对象。
这里涉及到了两个核心的类,分别是ConcurrentBag和PoolEntry
2、ConcurrentBag
1、PoolEntry :PoolEntry顾名思义是连接池的节点,里面有个connection属性,实际也可以看作是一个Connection对象的封装,连接池中存储的连接就是以PoolEntry的方式进行存储。
2、ConcurrentBag:ConcurrentBag本质就是连接池的主体,存储对象PoolEntry(PoolEntry主要是封装了connection),另外做了并发控制来解决连接池的并发问题。里面有锁对象,缓存PoolEntry集合,sharedList、threadList等。
/** 借出一个对象 */
public T borrow(long timeout
HikariCP连接池原理与管理:HikariDataSource与ConcurrentBag详解

最低0.47元/天 解锁文章
601

被折叠的 条评论
为什么被折叠?



