// 池中对象
private final T object;
// 初始化对象状态为 IDLE
private PooledObjectState state = PooledObjectState.IDLE; // @GuardedBy("this") to ensure transitions are valid
private final long createTime = System.currentTimeMillis();
private volatile long lastBorrowTime = createTime;
private volatile long lastUseTime = createTime;
private volatile long lastReturnTime = createTime;
private volatile boolean logAbandoned = false;
private volatile CallStack borrowedBy = NoOpCallStack.INSTANCE;
private volatile CallStack usedBy = NoOpCallStack.INSTANCE;
private volatile long borrowedCount = 0;
State
IDLE, //空闲状态 ALLOCATED, //从池中获取到对象后,allocate改变状态 IDLE -> ALLOCATED 使用中 EVICTION, EVICTION_RETURN_TO_HEAD, VALIDATION, VALIDATION_PREALLOCATED, VALIDATION_RETURN_TO_HEAD, INVALID, ABANDONED, RETURNING空闲检测
protected void setConfig(final BaseObjectPoolConfigconf) { setLifo(conf.getLifo()); setMaxWaitMillis(conf.getMaxWaitMillis()); setBlockWhenExhausted(conf.getBlockWhenExhausted()); setTestOnCreate(conf.getTestOnCreate()); setTestOnBorrow(conf.getTestOnBorrow()); setTestOnReturn(conf.getTestOnReturn()); setTestWhileIdle(conf.getTestWhileIdle()); setNumTestsPerEvictionRun(conf.getNumTestsPerEvictionRun()); setMinEvictableIdleTimeMillis(conf.getMinEvictableIdleTimeMillis()); // 延迟 + 定时 检测池中的空闲连接状态 setTimeBetweenEvictionRunsMillis(conf.getTimeBetweenEvictionRunsMillis()); setSoftMinEvictableIdleTimeMillis(conf.getSoftMinEvictableIdleTimeMillis()); final EvictionPolicy policy = conf.getEvictionPolicy(); if (policy == null) { // Use the class name (pre-2.6.0 compatible) setEvictionPolicyClassName(conf.getEvictionPolicyClassName()); } else { // Otherwise, use the class (2.6.0 feature) setEvictionPolicy(policy); } setEvictorShutdownTimeoutMillis(conf.getEvictorShutdownTimeoutMillis()); }
public void evict() throws Exception {
if (idleObjects.size() > 0) {//从队列中获取池化对象
PooledObject underTest = null;
// 获取 驱逐策略
final EvictionPolicy evictionPolicy = getEvictionPolicy();
synchronized (evictionLock) {
final EvictionConfig evictionConfig = new EvictionConfig(
getMinEvictableIdleTimeMillis(),
getSoftMinEvictableIdleTimeMillis(),
getMinIdle());
final boolean testWhileIdle = getTestWhileIdle();
// 获取需要检测的连接样本数【通过参数 NumTestsPerEvictionRun 设置空闲检测的样本数】
for (int i = 0, m = getNumTests(); i < m; i++) {
if (evictionIterator == null || !evictionIterator.hasNext()) {
evictionIterator = new EvictionIterator(idleObjects);
}
if (!evictionIterator.hasNext()) {
// Pool exhausted, nothing to do here
return;
}
try {
underTest = evictionIterator.next();
} catch (final NoSuchElementException nsee) {
i--;
evictionIterator = null;
continue;
}
if (!underTest.startEvictionTest()) {
i--;
continue;
}
boolean evict;
try {
// 通过 驱逐 策略验证空闲连接的有效性
evict = evictionPolicy.evict(evictionConfig, underTest,
idleObjects.size());
} catch (final Throwable t) {
PoolUtils.checkRethrow(t);
swallowException(new Exception(t));
// Don't evict on error conditions
evict = false;
}
if (evict) {// true 表示销毁连接
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
} else {
if (testWhileIdle) {// 如果设置为true,会定时检测 连接的有效性
boolean active = false;
try {
factory.activateObject(underTest);
active = true;
} catch (final Exception e) {
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
}
if (active) {
if (!factory.validateObject(underTest)) {
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
} else {
try {
factory.passivateObject(underTest);
} catch (final Exception e) {
destroy(underTest);
destroyedByEvictorCount.incrementAndGet();
}
}
}
}
if (!underTest.endEvictionTest(idleObjects)) {
// TODO - May need to add code here once additional
// states are used
}
}
}
}
}
...
}
驱逐策略
//EvictionConfig中idleEvictTime = BaseObjectPoolConfig#minEvictableIdleTimeMillis @Override public boolean evict(final EvictionConfig config, final PooledObjectunderTest, final int idleCount) { if ((config.getIdleSoftEvictTime() < underTest.getIdleTimeMillis() && config.getMinIdle() < idleCount) || config.getIdleEvictTime() < underTest.getIdleTimeMillis()) { return true; } return false; }
- 池中空闲连接大于最小连接数,并且池中连接空闲时间大于配置的IdleSoftEvictTime。
- 当检测的资源空闲时间过期后,即大于资源池配置的最小空闲时间,返回true。表示这些资源处于空闲状态,该此期间一直未被使用。
// 计算当前样本在池中空闲的时间
public long getIdleTimeMillis() {
// lastReturnTime 当前样本最近一次还回池中的时间
final long elapsed = System.currentTimeMillis() - lastReturnTime;
return elapsed >= 0 ? elapsed : 0;
}
Redis连接池
JedisConnectionConfiguration
初始化连接配置参数。
RedisAutoConfiguration#JedisConnectionConfiguration
private JedisClientConfiguration getJedisClientConfiguration() {
// JedisClientConfiguration.builder()
JedisClientConfigurationBuilder builder = applyProperties(JedisClientConfiguration.builder());
RedisProperties.Pool pool = this.properties.getJedis().getPool();
if (pool != null) {
applyPooling(pool, builder);
}
if (StringUtils.hasText(this.properties.getUrl())) {
customizeConfigurationFromUrl(builder);
}
// 自定义实现 连接池中的其他配置信息
customize(builder);
return builder.build();
}
private JedisClientConfigurationBuilder applyProperties(JedisClientConfigurationBuilder builder) {
if (this.properties.isSsl()) {
builder.useSsl();
}
if (this.properties.getTimeout() != null) {
Duration timeout = this.properties.getTimeout();
//设置连接、读超时
builder.readTimeout(timeout).connectTimeout(timeout);
}
return builder;
}
static JedisClientConfigurationBuilder builder() {
return new DefaultJedisClientConfigurationBuilder();
}
class DefaultJedisClientConfigurationBuilder{
// apache 实现的连接池框架中默认连接池配置类
private GenericObjectPoolConfig poolConfig = new JedisPoolConfig();
...
}
JedisPoolConfig设置一些连接池的默认值。
public JedisPoolConfig() {
// defaults to make your life with connection pool easier :)
setTestWhileIdle(true);
// 设置连接池中驱逐 空闲连接的最少时间【用于控制连接池中的最小连接数】
setMinEvictableIdleTimeMillis(60000);
// 设置开始 检测空闲连接的时间以及时间间隔
setTimeBetweenEvictionRunsMillis(30000);
setNumTestsPerEvictionRun(-1);
}
JedisClientConfigurationBuilderCustomizer自定义实现 连接池中的其他配置信息
@Component
public class JedisClientConfigurationCustomizer implements JedisClientConfigurationBuilderCustomizer {
@Override
public void customize(JedisClientConfiguration.JedisClientConfigurationBuilder clientConfigurationBuilder) {
JedisClientConfiguration build = clientConfigurationBuilder.build();
Optional poolConfig = build.getPoolConfig();
GenericObjectPoolConfig genericObjectPoolConfig = poolConfig.get();
genericObjectPoolConfig.setMaxWaitMillis(1000);
genericObjectPoolConfig.setMinEvictableIdleTimeMillis(10000);
genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(10000);
genericObjectPoolConfig.setNumTestsPerEvictionRun(10);
}
}
JedisConnectionFactory
class JedisConnectionFactory implements InitializingBean, DisposableBean, RedisConnectionFactory{
private final JedisClientConfiguration clientConfiguration;
private JedisConnectionFactory(JedisClientConfiguration clientConfig) {
this.clientConfiguration = clientConfig;
}
}
public void afterPropertiesSet() {
...
if (getUsePool() && !isRedisClusterAware()) {
// 将JedisConnectionFactory的配置信息与GenericObjectPool绑定,初始化连接池中的信息
this.pool = createPool();
}
}



