我在我的应用程序中使用连接池(snaq.db.ConnectionPool)。连接池初始化为:
String dburl = propertyUtil.getProperty("dburl");
String dbuserName = propertyUtil.getProperty("dbuserName");
String dbpassword = propertyUtil.getProperty("dbpassword");
String dbclass = propertyUtil.getProperty("dbclass");
String dbpoolName = propertyUtil.getProperty("dbpoolName");
int dbminPool = Integer.parseInt(propertyUtil.getProperty("dbminPool"));
int dbmaxPool = Integer.parseInt(propertyUtil.getProperty("dbmaxPool"));
int dbmaxSize = Integer.parseInt(propertyUtil.getProperty("dbmaxSize"));
long dbidletimeout = Long.parseLong(propertyUtil.getProperty("dbidletimeout"));
Class.forName(dbclass).newInstance();
ConnectionPool moPool = new ConnectionPool(dbpoolName, dbminPool, dbmaxPool, dbmaxSize,
dbidletimeout, dburl, dbuserName, dbpassword);
使用的DB池值是:
dbminPool=5
dbmaxPool=30
dbmaxSize=30
dbclass=org.postgresql.Driver
dbidletimeout=25
我的应用程序正在某处泄漏连接(连接未被释放),并且由于连接池已经耗尽。我现在已修复该代码。
空闲超时后不应关闭连接?如果这是不正确的假设,有没有办法关闭开放空闲连接(仅通过java代码)?
答案 0 :(得分:3)
您没有发布完整的代码,因此我假设您没有关闭连接。您仍然需要关闭从池中获取的连接对象,就像您没有使用池一样。关闭连接使池可以重新发出给另一个调用者。如果您未能执行此操作,最终将使用池中的所有可用连接。池的陈旧连接清除器不是清理连接的最佳位置。就像你的妈妈告诉你的那样,当你完成它们时,把你的东西拿走。
try {
conn = moPool.getConnection(timeout);
if (conn != null)
// do something
} catch (Exception e) {
// deal with me
} finally {
try {
conn.close();
} catch (Exception e) {
// maybe deal with me
}
}
答案 1 :(得分:3)
timeout
变量似乎不对应于连接空闲的时间,而是对应于池等待返回新连接或抛出异常的时间(我看了{{3} ,不知道它是否是最新的)。我认为跟踪“空闲”连接是相当困难的,因为在这种情况下“空闲”真正意味着什么?您可能希望获得连接以供以后使用。所以我想说连接池唯一的安全方式就是知道你完成了连接,就是在它上面调用close()
。
如果您担心开发团队忘记在他们的代码中调用close()
,我会在下面介绍一种技术,我过去曾使用过(在我的情况下,我们希望跟踪未关闭的{ {1}}但是概念是一样的。)
免责声明:
如上所述,主要思想是:我们有一个中心位置(连接池),我们从中获取资源(连接),我们希望跟踪我们的代码是否释放了这些资源。我们可以使用使用InputStream
对象的网络Filter
来跟踪请求期间使用的连接。我将此类命名为ThreadLocal
,并且跟踪资源的对象是TrackingFilter
类。
Tracker
要使public class TrackingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Tracker.start();
try {
chain.doFilter(request, response);
} finally {
Tracker.stop();
}
}
...
}
能够跟踪连接,每次使用Tracker
获取连接时以及每次使用{{1}关闭连接时都需要通知打电话。为了能够以对代码的其余部分透明的方式执行此操作,我们需要包装getConnection()
和返回的close()
对象。您的代码应该返回新的ConnectionPool
而不是原始池(我假设访问连接池的方式是在一个地方)。这个新池将依次包含它提供的每个Connection
,作为TrackingConnectionPool
。 Connection
是知道如何在创建时和关闭时通知我们TrackableConnection
的对象。
当您在请求结束时致电TrackableConnection
时,它会报告尚未调用Tracker
的任何连接。由于这是一个按请求操作,因此您只能识别错误操作(即在“创建新产品”功能期间),然后希望您能够跟踪那些留下开放连接并修复它们的查询。
您可以在下面找到Tracker.stop()
,close()
和TrackingConnectionPool
课程的代码和评论。为简洁起见,遗漏了代表方法。我希望有所帮助。
注意:对于包装器使用自动IDE功能(如Eclipse的“生成委托方法”),否则这将是一项耗时且容易出错的任务。
TrackableConnection
答案 2 :(得分:1)
连接池的重点是让pool为你处理所有这些事情。
closing open idle connections of java pool
的代码对您的情况无济于事。IDLE
或IN-USE
连接维护MAP的连接池。IN-USE
:如果应用程序正在引用连接对象,则会按池将其放入in-use-map
。IDLE
:如果应用程序/或closed
未引用连接对象,则会按池将其放入idle-map
。 idle
个关联都放入in-use-map
。idle-pool
没有任何可用条目,因此强制池会创建更多条目。IN-USE
。 open-idle-connections
,您可以通过代码关闭它。 当您修复代码中的连接泄漏时,您已尽力而为。
您可以force
发布池并重新创建一个。但是您必须小心,因为现有的连接可能会在其任务中受到影响。
答案 3 :(得分:0)
在大多数连接池中,空闲超时是连接池在连接池中空闲的最长时间(等待请求),而不是它在使用多长时间(从连接池中检出)。
某些连接池还具有允许连接使用多长时间的超时设置(例如,DBCP具有removeAbandonedTimeout
,c3p0具有unreturnedConnectionTimeout
),如果已启用并且超时已过期,他们将被强制撤销用户,并返回游泳池或真正关闭。
答案 4 :(得分:0)
log4jdbc可用于通过jdbc.connection
记录器缓解连接泄漏问题。
此技术不需要对代码进行任何修改。