栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

连接池关键源码理解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

连接池关键源码理解

DefaultPooledObject
// 池中对象
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 BaseObjectPoolConfig conf) {
    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 PooledObject underTest,
        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();
}

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/956000.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号