【发布时间】:2014-12-04 12:37:31
【问题描述】:
我们正在开发一个网站使用
- 雄猫 7
- JDBC
- PostgreSQL 9.2
我们有一些连接泄漏,并认为我们已经纠正了它们(数据库不再停止响应),但连接池的行为似乎仍然存在泄漏,因为我们有许多空闲连接大于上下文中设置的 maxIdle .xml。我想确保问题已得到解决。
出于测试目的,我使用以下 context.xml :
<Resource
auth="Container"
name="jdbc/postgres"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
type="javax.sql.DataSource"
username="admin"
password="..."
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://127.0.0.1:5432/..."
initialSize="1"
maxActive="50"
minIdle="0"
maxIdle="3"
maxWait="-1"
minEvictableIdleTimeMillis="1000"
timeBetweenEvictionRunsMillis="1000"
/>
如果我理解正确,我们应该在启动时有 1 个空闲连接,并且根据负载从 0 到 3,对吧?
发生的情况是:启动时有 1 个连接,如果负载低,则最多 3 个空闲连接,高负载后空闲连接超过 3 个。然后这些连接不会立即关闭,我们不知道它们何时/是否会关闭(有时其中一些会关闭)。
所以问题是:这种行为正常吗?
感谢您的帮助
EDIT:添加了工厂属性,并没有改变问题
编辑 2 :使用 removeAbandoned 和 removeAbandonedTimeout 使空闲连接在每个 removeAbandonedTimeout 时关闭。所以我们可能仍然有一些连接泄漏。以下是我们用来连接数据库并执行请求的一些代码:
PostgreSQLConnectionProvider,只是一个提供连接的静态类:
public class PostgreSQLConnectionProvider {
public static Connection getConnection() throws NamingException, SQLException {
String dsString = "java:/comp/env/jdbc/postgres";
Context context = new InitialContext();
DataSource ds = (DataSource) context.lookup(dsString);
Connection connection = ds.getConnection();
return connection;
}
}
DAO抽象类:
public abstract class DAO implements java.lang.AutoCloseable {
// Private attributes :
private Connection _connection;
// Constructors :
public DAO() {
try { _connection = PostgreSQLConnectionProvider.getConnection(); }
catch (NamingException | SQLException ex) {
Logger.getLogger(DAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Getters :
public Connection getConnection() { return _connection; }
// Closeable :
@Override
public void close() throws SQLException {
if(!_connection.getAutoCommit()) {
_connection.rollback();
_connection.setAutoCommit(true);
}
_connection.close();
}
}
UserDAO,一个小的 DAO 子类(我们有几个 DAO 子类来请求数据库):
public class UserDAO extends DAO {
public User getUserWithId(int id) throws SQLException {
PreparedStatement ps = null;
ResultSet rs = null;
User user = null;
try {
String sql = "select * from \"USER\" where id_user = ?;";
ps = getConnection().prepareStatement(sql);
ps.setInt(1, id);
rs = ps.executeQuery();
rs.next();
String login = rs.getString("login");
String password = rs.getString("password");
String firstName = rs.getString("first_name");
String lastName = rs.getString("last_name");
String email = rs.getString("email");
user = new User(id, login, password, firstName, lastName, email);
}
finally {
if(rs != null) rs.close();
if(ps != null) ps.close();
}
return user;
}
}
DAO 子类使用示例:
try(UserDAO dao = new UserDAO()) {
try {
User user = dao.getUserWithId(52);
}
catch (SQLException ex) {
// Handle exeption during getUserWithId
}
}
catch (SQLException ex) {
// Handle exeption during dao.close()
}
【问题讨论】:
-
尝试使用tomcat的连接池实现——功能更丰富,文档也不错people.apache.org/~fhanik/jdbc-pool/jdbc-pool.html
-
谢谢,不过这已经是我在做的了(你可以在context.xml中看到我使用的参数)。
-
我看不到主要部分 -
factory属性和适当的类名 -
哎呀你是对的,这个属性是必需的,我没有看到它。但是添加它并没有改变任何东西(我的参数已经被考虑在内:始终尊重initialSize)。
-
使用 removeAbandoned 和 removeAbandonedTimeout 会使空闲连接在每次 removeAbandonedTimeout 时消失,所以我想我们仍然有连接泄漏:/ .
标签: java postgresql tomcat connection-pooling