连接池的问题 我也正在做。
关键是线程锁的问题。其中getConnection() connection.close()即连接归还给池 以及后台监控连接池和作缓冲连接 这些操作之间的锁的控制很频繁。特别是处理监控这段特别值得注意:因为他与连接的得到和归还之间在大多时间情况下,不会造成死锁,容易存在隐患。所以未经过多次不同情况的测试和仔细分析检查很难发现。

其实死锁的问题关键是在于互锁的情况会不会发生。缓冲连接池上连接通常是由其它的锁控制的


private synchronized ConnectionWrapper getCon() throws SQLException {
ConnectionWrapper wrapper, con;
synchronized (conCountLock) {
for (int i = 0; i < conCount; i++) {
wrapper = wrappers[i];
if (wrapper == null)
continue;
synchronized (wrapper) {
if (wrapper.checkedout)
continue;
wrapper.setConnection(cons[i]);
wrapper.checkedout = true;
wrapper.lockTime = System.currentTimeMillis();
LOG.debug("Find connection cons[]:"+i);

}
return wrapper;
}
if (conCount >= maxCon)
return null;

con = createCon(conCount);
conCount++;

}
return con;
}

某种意义上讲并发同时得到连接是不可能的,但作为缓冲连接池,上面得到连接是快速的,这正是其区别于直接连接数据库的根本区别。也就是用出。

可数据库缓冲连接池第二个工作是维护连接,虽然不必经常做,通常设为半分钟。其处理连接内的警告信息,以及连接情况连接超时情况,连接过多且未使用情况,这时容易与程序中其他想得到连接的线程在得到连接时发生死锁。


public void run() {

Statement stmt = null;
do {
LOG.debug("backgroud hourse keep thread run ...");
for (int i = 0; i < maxCon; i++) {
if (cons[i] != null)
try {
java.sql.SQLWarning warning = cons[i].getWarnings();
if (warning != null) {
LOG.warn("Connection " + i + " had warnings: " + warning);
cons[i].clearWarnings();
}
}
catch (SQLException e) {
LOG.warn("Unable to get warning for connection: ", e);
}
}

int lastOpen = -1;
for (int i = maxCon - 1; i >= 0; i--) {
if (wrappers[i] == null)
continue;
long time = 0;
try {
time = System.currentTimeMillis();

synchronized (wrappers[i]) {
if (!wrappers[i].checkedout) {
wrappers[i].checkedout = true;

}
else {

if (lastOpen < i)
lastOpen = i;

if (LOG.isDebugEnabled() &&!wrappers[i].hasLoggedException &&
time - wrappers[i].lockTime > 90000L) {
wrappers[i].hasLoggedException = true;


LOG.warn("Connection has been held open for too long: ",wrappers[i].exception);
}


continue;

}
}
stmt = cons[i].createStatement();

if (cons[i].isClosed())
throw new SQLException();
if (time - wrappers[i].createTime > (long) conTimeout)
throw new SQLException();
if (time - wrappers[i].checkinTime > 60000L &&
i > minCon &&
lastOpen <= i) {
LOG.debug("% checkin too long time and i:"+i+"> minCon and "+lastOpen+"<=i");
synchronized (conCountLock) {
cons[i].close();
wrappers[i] = null;
cons[i] = null;
conCount--;
lastOpen = i;
}

}
synchronized (wrappers[i]) {
if (wrappers[i] != null)
wrappers[i].checkedout = false;
}

}
catch (SQLException e) {
try {
synchronized (conCountLock) {
cons[i].close();
wrappers[i] = createCon(i);
wrappers[i].checkedout = false;
LOG.debug("reconnect wrappers[]:"+i);
}
}
catch (SQLException sqle) {
LOG.warn("Failed to reopen connection", sqle);
synchronized (conCountLock) {
wrappers[i] = null;
cons[i] = null;
conCount--;
}
}
//i--;
}
finally {
try {
if (stmt != null) {
stmt.close();
}
}
catch (SQLException e1) {}

}

}

try {
Thread.sleep(30000L);
}
catch (InterruptedException e) {
return;
}
}
while (true);
}

行了,该结束了,不要再贴下去了,再贴下去成了闹剧了!看着都肉麻 :)

虽然这里有人认为我是技术高手,但我自己知道我不是真正的高手,我心目中真正的高手是那些编写JBoss,编写Hibernate的人。别人吹捧有他自己的理由,我无权过问,只不管如果我拼命谦虚反倒显得矫情了,所以就不做声了。

我不会对那些我认为技术很菜的人摆谱,也不会摆出一副自己高高在上的架子,瞧不起别人。有时候我的语气确实比较强硬,甚至霸道,那不是因为技术上的原因,是因为对某些人的态度看不惯,(比如说像TSS的人随便搞个测试就信口开河)不是态度狂不狂的问题,而是有没有负责任的态度,如果有足够的说服力,再狂我也会低头,记得前面Jevang还用rant(咆哮)这个词来说我,我也没有觉得不爽啊。反正论坛就是一个娱乐的地方,大家都别太认真了,一认真就得出问题了。:)

b]“大家研究一下吗
何必认真呢!”[

cut off吧。
大家都是为了提高自己,别的没什么意思。

这一句我不太懂:
synchronized (conCountLock) {
cons<i>.close();
wrappers<i> = null;
cons<i> = null;
conCount--;
lastOpen = i;
}

synchronized (conCountLock) 是什么,方法?程序块,是循环的吗?conCountLock是什么,也没有定义,也没有使用。

猪猪们请正常讨论,不要老是义愤填膺的,不要老是愤世嫉俗的。

synchronized(conCountLock){
是同步块
此段代码使用conCountLock锁同步。
凡是牵扯到连接的改变的地方,使用该锁做同步处理!

Sinoi_Feng,
I was very surprised to see your test result, it's must be too much overhead in your poolmanager to control the rendering and releasing of connections, which is not even synchronization related( since you have not run concurrency test, so threading issue is unknown), but I think it's PART of a valid test case.

Robbin's initial comment and some others' here maybe little bit harsh and off the topic. People tend to over-estimate the concurrency support requrement of connection pooling and over-engineering the implementation: connection normally come and go in sub-second or seconds, but each invocation is rarely measurable by millis. The phenomena given by Robbin is a classic threading issue and can be well applied to many resource management sections such as cache, queue or event listeners, but not really mean much to connection pool in general. As a matter of fact, all middle ware products have some kind of funnel styled setting to protect threads get thrashed.

My connection pool use a simple java.util.Stack, which supposed to perform horribly under heavier context switching ( There are many good articles, best one is Doug Lee's book), but in the past 7 years in use, it never become the hotspot as there are never that many concurrent accesses, even one pool is serving over 1000 active users.

Multiple threading test is necessary step, but if you already have problem with pool size expanding but not thread count increase, then it's more critical to be fixed.

BTW, keep over 100 connection in a pool seems quite high, true scalable app should not be designed to hold on resources for too long, I don't know who said that "Architecture is key to optimization"

Cheers
-Jevang

?
:(