文本主要研究一下jedis连接池对commons-pool的封装
jedis-3.8.0-sources.jar!/redis/clients/jedis/JedisPoolConfig.java
public class JedisPoolConfig extends GenericObjectPoolConfig {
public JedisPoolConfig() {
// defaults to make your life with connection pool easier :)
setTestWhileIdle(true);
setMinEvictableIdleTimeMillis(60000);
setTimeBetweenEvictionRunsMillis(30000);
setNumTestsPerEvictionRun(-1);
}
}
JedisPoolConfig继承了GenericObjectPoolConfig,在构造器里头设置了默认的参数,即testWhileIdle为true,minEvictableIdleTime为60s,timeBetweenEvictionRuns为30s,numTestsPerEvictionRun为-1
见上一篇文章聊聊JedisFactory
jedis-3.8.0-sources.jar!/redis/clients/jedis/util/Pool.java
public abstract class Pool implements Closeable {
/**
* @deprecated This will be private in future.
*/
@Deprecated
protected GenericObjectPool internalPool;
public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory factory) {
initPool(poolConfig, factory);
}
/**
* @param poolConfig
* @param factory
* @deprecated This method will be private in future.
*/
@Deprecated
public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory factory) {
if (this.internalPool != null) {
try {
closeInternalPool();
} catch (Exception e) {
}
}
this.internalPool = new GenericObjectPool<>(factory, poolConfig);
}
public T getResource() {
try {
return internalPool.borrowObject();
} catch (NoSuchElementException nse) {
if (null == nse.getCause()) { // The exception was caused by an exhausted pool
throw new JedisExhaustedPoolException(
"Could not get a resource since the pool is exhausted", nse);
}
// Otherwise, the exception was caused by the implemented activateObject() or ValidateObject()
throw new JedisException("Could not get a resource from the pool", nse);
} catch (Exception e) {
throw new JedisConnectionException("Could not get a resource from the pool", e);
}
}
public void returnResource(final T resource) {
if (resource != null) {
returnResourceObject(resource);
}
}
/**
* @param resource
* @deprecated This will be removed in next major release. Use {@link Pool#returnResource(java.lang.Object)}.
*/
@Deprecated
protected void returnResourceObject(final T resource) {
try {
internalPool.returnObject(resource);
} catch (RuntimeException e) {
throw new JedisException("Could not return the resource to the pool", e);
}
}
public void destroy() {
closeInternalPool();
}
/**
* @deprecated This will be removed in next major release. Use {@link Pool#destroy()}.
*/
@Deprecated
protected void closeInternalPool() {
try {
internalPool.close();
} catch (RuntimeException e) {
throw new JedisException("Could not destroy the pool", e);
}
}
/**
* @param resource
* @deprecated This will be removed in next major release. Use {@link Pool#returnBrokenResource(java.lang.Object)}.
*/
@Deprecated
protected void returnBrokenResourceObject(final T resource) {
try {
internalPool.invalidateObject(resource);
} catch (Exception e) {
throw new JedisException("Could not return the broken resource to the pool", e);
}
}
//......
}
Pool声明实现Closeable接口,它的构造器根据GenericObjectPoolConfig和PooledObjectFactory来创建GenericObjectPool,它的getResource、returnResource、returnBrokenResourceObject、destroy方法内部都是委托给了GenericObjectPool
它有一个实现类JedisPoolAbstract,而JedisPoolAbstract还有两个子类,分别是JedisPool、JedisSentinelPool
jedis-3.8.0-sources.jar!/redis/clients/jedis/JedisPoolAbstract.java
/**
* @deprecated This class will be removed in future. If you are directly manipulating this class,
* you are suggested to change your code to use {@link Pool Pool<Jedis>} instead.
*/
@Deprecated
public class JedisPoolAbstract extends Pool {
/**
* Using this constructor means you have to set and initialize the internalPool yourself.
*
* @deprecated This constructor will be removed in future.
*/
@Deprecated
public JedisPoolAbstract() {
super();
}
public JedisPoolAbstract(GenericObjectPoolConfig poolConfig,
PooledObjectFactory factory) {
super(poolConfig, factory);
}
}
这个类未来将要被废弃,它主要是设置了Pool的泛型为Jedis
jedis-3.8.0-sources.jar!/redis/clients/jedis/JedisPool.java
public class JedisPool extends JedisPoolAbstract {
//......
@Override
public Jedis getResource() {
Jedis jedis = super.getResource();
jedis.setDataSource(this);
return jedis;
}
@Override
public void returnResource(final Jedis resource) {
if (resource != null) {
try {
resource.resetState();
returnResourceObject(resource);
} catch (RuntimeException e) {
returnBrokenResource(resource);
log.warn("Resource is returned to the pool as broken", e);
}
}
}
}
JedisPool覆盖了getResource和returnResource方法,其中getResource新增了设置dataSource给jedis;returnResource方法新增了jedis的resetState操作,return有异常的话会执行returnBrokenResource
jedis-3.8.0-sources.jar!/redis/clients/jedis/JedisSentinelPool.java
public class JedisSentinelPool extends JedisPoolAbstract {
@Override
public Jedis getResource() {
while (true) {
Jedis jedis = super.getResource();
jedis.setDataSource(this);
// get a reference because it can change concurrently
final HostAndPort master = currentHostMaster;
final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(), jedis.getClient()
.getPort());
if (master.equals(connection)) {
// connected to the correct master
return jedis;
} else {
returnBrokenResource(jedis);
}
}
}
@Override
public void returnResource(final Jedis resource) {
if (resource != null) {
try {
resource.resetState();
returnResourceObject(resource);
} catch (RuntimeException e) {
returnBrokenResource(resource);
log.debug("Resource is returned to the pool as broken", e);
}
}
}
//......
}
JedisSentinelPool覆盖了getResource和returnResource方法,其中getResource新增了设置dataSource给jedis,然后判断master;returnResource方法新增了jedis的resetState操作,return有异常的话会执行returnBrokenResource
jedis主要有三个对象对commons-pool进行包装,分别是JedisPoolConfig(继承了GenericObjectPoolConfig
),JedisFactory(实现了PooledObjectFactory
)、Pool(提供了get和return方法,内部委托给GenericObjectPool
)
JedisPoolConfig继承了GenericObjectPoolConfig,在构造器里头设置了默认的参数,即testWhileIdle为true,minEvictableIdleTime为60s,timeBetweenEvictionRuns为30s,numTestsPerEvictionRun为-1