[Ngbatis源码学习]Ngbatis源码阅读之连接池的创建
Ngbatis源码阅读之连接池的创建
1. NebulaPool的创建
NgbatisBeanFactoryPostProcessor 这个类实现了 BeanFactoryPostProcessor 后置处理器,Ngbatis 连接池的创建就在 postProcessBeanFactory 中实现。关于 BeanFactoryPostProcessor 的有关内容可以参考上一篇文章。
首先来看 org.nebula.contrib.ngbatis.NgbatisBeanFactoryPostProcessor#postProcessBeanFactory 方法,代码如下:
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
NebulaPool nebulaPool = nebulaPool();
// ... 省略部分代码 ...
}
进入 org.nebula.contrib.ngbatis.NgbatisBeanFactoryPostProcessor#nebulaPool 方法:
public NebulaPool nebulaPool() {
NebulaPool pool = new NebulaPool();
try {
// 传入地址集合与线程池配置参数
pool.init(
nebulaJdbcProperties.getHostAddresses(),
nebulaJdbcProperties.getPoolConfig()
);
} catch (UnknownHostException e) {
throw new RuntimeException("Can not connect to Nebula Graph");
}
return pool;
}
可以看到主要调用了 init 方法。init 方法传入了两个参数,一个是地址集合参数,一个是线程池配置参数。这两个参数都是通过 yml 配置文件来获取得到。进入 com.vesoft.nebula.client.graph.net.NebulaPool#init 方法:
public boolean init(List<HostAddress> addresses, NebulaPoolConfig config) throws UnknownHostException, InvalidConfigException {
// 检查是否已经初始化
checkInit();
// 设置是否初始化参数为true
hasInit.set(true);
// 检查配置参数是否正确
checkConfig(config);
// 等待时间
this.waitTime = config.getWaitTime();
// 支持配置多个NebulaGraph连接地址
List<HostAddress> newAddrs = hostToIp(addresses);
// 根据是否ssl获取负载均衡器(负载均衡策略:轮询)
this.loadBalancer = config.isEnableSsl()
? new RoundRobinLoadBalancer(newAddrs, config.getTimeout(), config.getSslParam(),
config.getMinClusterHealthRate())
: new RoundRobinLoadBalancer(newAddrs, config.getTimeout(),
config.getMinClusterHealthRate());
// 根据负载均衡器、配置、 GenericObjectPool 对象池技术创建连接池
ConnObjectPool objectPool = new ConnObjectPool(this.loadBalancer, config);
this.objectPool = new GenericObjectPool<>(objectPool);
// 配置相关配置
GenericObjectPoolConfig objConfig = new GenericObjectPoolConfig();
objConfig.setMinIdle(config.getMinConnSize());
objConfig.setMaxIdle(config.getMaxConnSize());
objConfig.setMaxTotal(config.getMaxConnSize());
objConfig.setTestOnBorrow(true);
objConfig.setTestOnReturn(true);
objConfig.setTestOnCreate(true);
objConfig.setTestWhileIdle(true);
objConfig.setTimeBetweenEvictionRunsMillis(config.getIntervalIdle() <= 0
? BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS
: config.getIntervalIdle());
objConfig.setSoftMinEvictableIdleTimeMillis(config.getIdleTime() <= 0
? BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS
: config.getIdleTime());
this.objectPool.setConfig(objConfig);
AbandonedConfig abandonedConfig = new AbandonedConfig();
abandonedConfig.setRemoveAbandonedOnBorrow(true);
this.objectPool.setAbandonedConfig(abandonedConfig);
// 连接池初始化
return objectPool.init();
}
可以看到 NebulaGraph 的连接池其实就是基于 apache commons-pool2 对象池框架对连接进行了池化管理。
以下补充相关核心类 GenericObjectPool 和 GenericObjectPoolConfig 的介绍。
2. GenericObjectPool
Apache Commons Pool
是一个对象池的框架,它提供了一整套用于实现对象池化的API。它提供了三种对象池:GenericKeyedObjectPool
,SoftReferenceObjectPool
和 GenericObjectPool
,其中 GenericObjectPool
是最常用的对象池。
对象池的技术其实很常见,比如线程池、数据库连接池,都是针对对象创建代价高,比较消耗资源和性能这些问题得出的解决方案,即使用完对象后不立即释放资源,而是放到一个池子里存起来,下次就能直接从池子里拿出现成可用的对象。
对象池需要具备以下能力:
- 首先得有个容器数据结构,能存放多个对象,也有数量上限
- 维持一定数量的常驻对象,当数量与
QPS * RT
匹配的话,业务处理就能直接获取可用对象,不需要消耗对象创建的时间 - 能应对突发的流量
- 一定时间内没有获取成功就抛出异常,不会卡死业务现成
- 具有活性检测机制,从容器中拿出来的对象是可用的
对象获取的核心流程是:
3. GenericObjectPoolConfig
GenericObjectPoolConfig 是在 GenericObjectPool 构造的时候用的,用来设置 pool 的一些属性。
代码如下:
public class GenericObjectPoolConfig<T> extends BaseObjectPoolConfig<T> {
public static final int DEFAULT_MAX_TOTAL = 8;
public static final int DEFAULT_MAX_IDLE = 8;
public static final int DEFAULT_MIN_IDLE = 0;
private int maxTotal = 8;
private int maxIdle = 8;
private int minIdle = 0;
public GenericObjectPoolConfig() {
}
public GenericObjectPoolConfig<T> clone() {
try {
return (GenericObjectPoolConfig)super.clone();
} catch (CloneNotSupportedException var2) {
throw new AssertionError();
}
}
// ... 省略部分代码 ...
}
可以看到在 GenericObjectPoolConfig 中主要配置了 maxTotal、maxIdle、minIdle:
-
maxTotal
:对象池中允许的最大对象个数。在从对象池获取对象时,如果对象池中有Idle对象,则直接返回一个对象。否则,判断活跃对象是否已经达到maxTotal,是就会发生阻塞等待,直到有对象归还对象池;没有达到maxTotal,则就会创建一个新对象供使用。
-
maxIdle
:对象池中最大空闲的对象个数。在归还对象时,对象会处于Idle状态,这时,对象池会判断Idle对象个数,如果已经达到maxIdle,则对象会被直接销毁,否则才会放回对象池
-
minIdle
:对象池中最小空闲的对象个数, 默认为0。new一个对象池时,会初始创建minIdle个对象。当开启了回收机制后,如果对象空闲时间达到了设定值,则会被销毁、移出对象池。但对象池中至少会保留minIdle个对象。
其实还有其他很多属性,都在父类 BaseObjectPoolConfig 中,浅看一眼:
public abstract class BaseObjectPoolConfig<T> extends BaseObject implements Cloneable {
// ...
private Duration maxWaitDuration;
private Duration minEvictableIdleDuration;
private Duration evictorShutdownTimeoutDuration;
private Duration softMinEvictableIdleDuration;
private int numTestsPerEvictionRun;
private EvictionPolicy<T> evictionPolicy;
private String evictionPolicyClassName;
private boolean testOnCreate;
private boolean testOnBorrow;
private boolean testOnReturn;
private boolean testWhileIdle;
private Duration durationBetweenEvictionRuns;
private boolean blockWhenExhausted;
private boolean jmxEnabled;
private String jmxNamePrefix;
private String jmxNameBase;
// ...
}
本文来自博客园,作者:knqiufan,转载请注明原文链接:https://www.cnblogs.com/knqiufan/p/17880778.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本