我們正在開發使用Tomcat的連接池和空閒連接
- 的Tomcat 7
- JDBC
- 的PostgreSQL 9.2
我們已經有一些連接泄漏,並認爲我們糾正他們的網站(數據庫不再停止響應),但連接池的行爲似乎仍然存在漏洞,因爲我們有大量空閒連接大於context.xml中設置的maxIdle。我想確定問題已解決。
出於測試目的,我使用了以下的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使閒置CONNEXIONS被每逢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 sublasses請求數據庫):
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的連接池實現 - 功能更豐富,並且具有良好的文檔https://people.apache.org/~fhanik/jdbc-pool/jdbc-pool.html – 2014-10-09 16:35:51
謝謝,但它已經我在做什麼(你可以在context.xml中看到我使用的參數)。 – 2014-10-09 18:57:23
我看不到主要部分 - 「工廠」屬性和適當的類名稱 – 2014-10-09 19:09:57