其实这篇文章的题目,应该叫谈谈Apache common pool的连接池技术


这篇博客,就不怎么分析源码了,咱们尽量把观察的层次提高一下,主要分析流程。


下图是JedisPool里面用到的一些类(有些类我省略了,例如closeable)

谈谈Jedis的连接池技术_Pool


PooledObjectFactory<T>,是一个泛型接口,里面有makeObjcet,destroyObject,validateObject等方法,就是生成一个对象,销毁一个对象,判定是否合法等的

PooledObject 是对基本对象的一个包装,包含基本对象的创建时间,状态等等

GenericObjectPool 里面包含了borrowObject与returnObject等方法



我们一般的从pool中取对象调用的是JedisPool的getResource方法

时序图如下:

谈谈Jedis的连接池技术_连接池_02


在GenericObjectPool中有下面这个成员变量:

private final LinkedBlockingDeque<PooledObject<T>> idleObjects;

在上面时序图里第三步create前,会先在idleObjects里面找(idleObjects.pollFirst()),如果没有对象(这是一个队列),才去create,否则就直接返回idleobjects里面的。

释放连接,我们一般直接调用jedis的close方法。

如下图

谈谈Jedis的连接池技术_连接池_03



最后那个LinkedBlockingDeque就是idleObjects。



当然,我上面的时序图,是我省略了很多很多的,但是主体就是上面的。

另外,pool的源码我自己看的也比较粗,如果文中有什么错误,还请各位大神一定指出。


有一个问题,如果我给pool设置的最少连接是20

那么这20个连接时连接池一开始就循环产生的,还是后面借一个,才生出一个?

换句话说就是勤生产还是懒生产。

答案是勤生产(准确的说是,自pool加载后timeBetweenEvictionRunsMillis毫秒开始生产这个连接对象,timeBetweenEvictionRunsMillis模式是30000毫秒)

timeBetweenEvictionRunsMillis毫秒秒检查一次连接池中空闲的连接,把空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开,直到连接池中的连接数到minIdle为止

谈谈Jedis的连接池技术_ico_04

   

//GenericObjectPool.java
void ensureMinIdle() throws Exception {
ensureIdle(getMinIdle(), true);
}


private void ensureIdle(int idleCount, boolean always) throws Exception {
if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
return;
}


while (idleObjects.size() < idleCount) {
PooledObject<T> p = create();
if (p == null) {
// Can't create objects, no reason to think another call to
// create will work. Give up.
break;
}
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();
}
}