gpt4 book ai didi

java - Tomcat连接池&空闲连接

转载 作者:行者123 更新时间:2023-11-29 13:29:57 25 4
gpt4 key购买 nike

我们正在开发一个网站,使用

  • Tomcat 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 个空闲连接。然后这些连接并没有立即关闭,我们不知道它们何时/是否会关闭(有时其中一些会关闭)。

所以问题是:这种行为是否正常?

谢谢你的帮助

编辑:添加工厂属性,没有改变问题

编辑 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()
}

最佳答案

查看代码,似乎连接是在 DAO 的生命周期内获取的,而不是语句的生命周期,这是通常的预期。通常,您会在即将执行语句时从池中获取一个连接,并在完成后对其调用 close() 以将其返回到池中。

此外,在您的 finally 子句中,rs.close()ps.close() 都可能抛出异常,从而导致错过对准备好的语句的最后一次调用。

在 Java 7 中,您还可以使用 try with resources将为您关闭准备好的语句和连接的语句。根据规范,驱动程序应该在语句关闭时为您关闭结果。

关于java - Tomcat连接池&空闲连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26280832/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com