一、jedis连接池
jedis是连接redis的java客户端,连接池负责管理jedis与redis服务器的连接。
二、连接池创建
JedisPool提供了很多构造方法,可根据需要调用,如public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port, int timeout, final String password)
最终都会调用父类pool的方法:
public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
initPool(poolConfig, factory);
}
public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
if (this.internalPool != null) {
try {
closeInternalPool();
} catch (Exception e) {
}
}
this.internalPool = new GenericObjectPool<T>(factory, poolConfig);
}
最终调用通用对象连接池GenericObjectPool类创建连接池。
public GenericObjectPool(PooledObjectFactory<T> factory,
GenericObjectPoolConfig config) {
super(config, ONAME_BASE, config.getJmxNamePrefix());
if (factory == null) {
jmxUnregister(); // tidy up
throw new IllegalArgumentException("factory may not be null");
}
this.factory = factory;
//创建连接对象队列
idleObjects = new LinkedBlockingDeque<PooledObject<T>>(config.getFairness());
//设置配置参数
setConfig(config);
startEvictor(getTimeBetweenEvictionRunsMillis()); // 启动定时任务回收空闲连接
}
private final Map<IdentityWrapper<T>, PooledObject<T>> allObjects =
new ConcurrentHashMap<IdentityWrapper<T>, PooledObject<T>>(); // 除了被销毁的所有对象
private final LinkedBlockingDeque<PooledObject<T>> idleObjects;// 空闲对象
三、获取连接
获取连接入口方法在JedisPool的
public Jedis getResource() {
Jedis jedis = super.getResource();jedis.setDataSource(this);
return jedis;
}
调用父类pool的public T getResource() {
try {
return internalPool.borrowObject();
} catch (NoSuchElementException nse) {
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);
}
}
从连接池里获取连接,获取连接核心代码GenericObjectPool的borrowObject方法:
public T borrowObject(long borrowMaxWaitMillis) throws Exception {
assertOpen();
AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
(getNumIdle() < 2) &&
(getNumActive() > getMaxTotal() - 3) ) {
removeAbandoned(ac);
}
PooledObject<T> p = null;
// 连接池没有可用连接(无空闲或为空)是否阻塞等待
boolean blockWhenExhausted = getBlockWhenExhausted();
boolean create; //本次连接是否新创建标志
long waitTime = System.currentTimeMillis();
while (p == null) {
create = false;
if (blockWhenExhausted) {
p = idleObjects.pollFirst();//返回空闲连接队列的第一个对象
if (p == null) {
p = create();// 创建新连接
if (p != null) {
create = true;
}
}
if (p == null) {
if (borrowMaxWaitMillis < 0) {
p = idleObjects.takeFirst(); //阻塞获取空闲队列的第一个连接对象
} else {
p = idleObjects.pollFirst(borrowMaxWaitMillis,
TimeUnit.MILLISECONDS);//根据超时时间返回空闲连接队列的第一个对象
}
}
if (p == null) {
throw new NoSuchElementException(
"Timeout waiting for idle object");
}
if (!p.allocate()) {
p = null;
}
} else {
p = idleObjects.pollFirst();
if (p == null) {
p = create();
if (p != null) {
create = true;
}
}
if (p == null) {
throw new NoSuchElementException("Pool exhausted");
}
if (!p.allocate()) {
p = null;
}
}
if (p != null) {try {
factory.activateObject(p); //激活资源对象
} catch (Exception e) {
try {
destroy(p);
} catch (Exception e1) {
// Ignore - activation failure is more important
}
p = null;
if (create) {
NoSuchElementException nsee = new NoSuchElementException(
"Unable to activate object");
nsee.initCause(e);
throw nsee;
}
}
if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
boolean validate = false;
Throwable validationThrowable = null;
try {
validate = factory.validateObject(p); //检查对象是否有效
} catch (Throwable t) {
PoolUtils.checkRethrow(t);
validationThrowable = t;
}
if (!validate) {
try {
destroy(p); //无效时销毁对象
destroyedByBorrowValidationCount.incrementAndGet();
} catch (Exception e) {
// Ignore - validation failure is more important
}
p = null;
if (create) {
NoSuchElementException nsee = new NoSuchElementException(
"Unable to validate object");
nsee.initCause(validationThrowable);
throw nsee;
}
}
}
}
}
updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
return p.getObject();
}
当没有可用连接调用create方法创建资源对象代码:
private PooledObject<T> create() throws Exception {
int localMaxTotal = getMaxTotal();
long newCreateCount = createCount.incrementAndGet();
if (localMaxTotal > -1 && newCreateCount > localMaxTotal ||
newCreateCount > Integer.MAX_VALUE) {
createCount.decrementAndGet();
return null;
}
final PooledObject<T> p;
try {
p = factory.makeObject(); //调用工厂类创建对象
} catch (Exception e) {
createCount.decrementAndGet();
throw e;
}
AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getLogAbandoned()) {
p.setLogAbandoned(true);
}
createdCount.incrementAndGet();
allObjects.put(new IdentityWrapper<T>(p.getObject()), p);
return p;
}
工厂类JedisFactory创建资源连接对象代码:
public PooledObject<Jedis> makeObject() throws Exception {
final HostAndPort hostAndPort = this.hostAndPort.get();
final Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort(), connectionTimeout,
soTimeout, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
try {
jedis.connect();
if (null != this.password) {
jedis.auth(this.password);
}
if (database != 0) {
jedis.select(database);
}
if (clientName != null) {
jedis.clientSetname(clientName);
}
} catch (JedisException je) {
jedis.close();
throw je;
}
return new DefaultPooledObject<Jedis>(jedis);
}
四、关闭连接
获取连接后需要调用关闭连接jedis.close();方法,释放连接,该方法只是释放资源到连接池,并不会真正关闭与redis服务器的连接。
Jedis类的close代码:
public void close() {
if (dataSource != null) { //如果有连接池,就调用连接池的方法
if (client.isBroken()) {
this.dataSource.returnBrokenResource(this);
} else {
this.dataSource.returnResource(this);
}
} else { // 如果没有连接池,则直接断开与服务器的连接
client.close();
}
}
JredisPool类returnResource释放连接的代码:
public void returnResource(final Jedis resource) {
if (resource != null) {
try {
resource.resetState();
returnResourceObject(resource);
} catch (Exception e) {
returnBrokenResource(resource);
throw new JedisException("Could not return the resource to the pool", e);
}
}
}
public void returnResourceObject(final T resource) {
if (resource == null) {
return;
}
try {
internalPool.returnObject(resource);
} catch (Exception e) {
throw new JedisException("Could not return the resource to the pool", e);
}
}
释放资源的核心方法returnObject代码:
public void returnObject(T obj) {
PooledObject<T> p = allObjects.get(new IdentityWrapper<T>(obj)); // 获取要释放的连接
if (p == null) {
if (!isAbandonedConfig()) {
throw new IllegalStateException(
"Returned object not currently part of this pool");
} else {
return; // Object was abandoned and removed
}
}
synchronized(p) {
final PooledObjectState state = p.getState();
if (state != PooledObjectState.ALLOCATED) {
throw new IllegalStateException(
"Object has already been returned to this pool or is invalid");
} else {
p.markReturning(); // Keep from being marked abandoned
}
}
long activeTime = p.getActiveTimeMillis();
if (getTestOnReturn()) {
if (!factory.validateObject(p)) {
try {
destroy(p); //销毁对象
} catch (Exception e) {
swallowException(e);
}
try {
ensureIdle(1, false);
} catch (Exception e) {
swallowException(e);
}
updateStatsReturn(activeTime);
return;
}
}
try {
factory.passivateObject(p); //钝化对象
} catch (Exception e1) {
swallowException(e1);
try {
destroy(p);
} catch (Exception e) {
swallowException(e);
}
try {
ensureIdle(1, false);
} catch (Exception e) {
swallowException(e);
}
updateStatsReturn(activeTime);
return;
}
if (!p.deallocate()) {
throw new IllegalStateException(
"Object has already been returned to this pool or is invalid");
}
int maxIdleSave = getMaxIdle();
if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) { //如果空闲队列已达到配置值,则直接销毁连接
try {
destroy(p);
} catch (Exception e) {
swallowException(e);
}
} else {
if (getLifo()) {
idleObjects.addFirst(p);} else {
idleObjects.addLast(p);
} //将连接放入空闲对象队列,默认先进先出
if (isClosed()) {
// Pool closed while object was being added to idle objects.
// Make sure the returned object is destroyed rather than left
// in the idle object pool (which would effectively be a leak)
clear();
}
}
updateStatsReturn(activeTime);
}