Tomcat 9 的 Oracle 僵尸连接
Oracle zombie connections with Tomcat 9
我在 Tomcat 9.0.12 上创建了一个非常简单的 Web 服务,每次调用它时,我都会使用数据源(在 conf/context 中定义)创建到数据库 (Oracle 12) 的连接.xml 文件)然后在将响应返回给客户端之前,它会关闭与数据库的连接。
但是如果我检查我的数据库上的活动会话,它会显示连接仍然存在,所以我有很多 "zombie" 连接到我的数据库。
我在客户端程序中使用了大致相同的代码,在这种情况下程序关闭了连接。也许是 Tomcat 错误的配置?
我该如何解决这个问题?
谢谢!
conf/context.xml
<Resource maxWaitMillis="5000"
maxIdle="100"
maxActive="200"
password="PASSWORD"
username="USER"
url="jdbc:oracle:thin:@/192.168.1.248:1521/PRD"
driverClassName="oracle.jdbc.driver.OracleDriver"
type="javax.sql.DataSource"
auth="Container"
name="jdbc_Connection"/>
Java
public String method() {
try {
System.out.println("---------------------------------------");
System.out.println("START");
System.out.println("---------------------------------------");
DataSource ds = (DataSource) InitialContext.doLookup("java:comp/env/jdbc_Connection");
Connection DB = ds.getConnection();
String sql ="SELECT VAR FROM TABLE_NAME";
PreparedStatement stmt = null;
try {
stmt = DB.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
while(rs.next()){
System.out.println("rs->"+rs.getString(1));
}
rs.close();
stmt.close();
} catch (SQLException ex) {
}finally{
if(stmt != null){
try {
stmt.close();
} catch (SQLException ex) {
}
}
}
System.out.println("CLOSE");
DB.close();
} catch (SQLException ex) {
ex.printStackTrace();
} catch (NamingException ex) {
ex.printStackTrace();
}
System.out.println("---------------------------------------");
System.out.println("END");
System.out.println("---------------------------------------");
return "HELLO";
}
他们不是僵尸。他们在连接池中等待重用。创建连接是昂贵的,所以你不想(真的)白白关闭它们。正如 Andreas 指出的那样,连接池 return 是一个包装连接,其中调用 close()
并没有真正关闭它。它只是 return 进入游泳池。
您的配置表明池中最多可以有 100 个空闲连接,总连接数为 200。正如马克所说,这可能是 way too much。
我在 Tomcat 9.0.12 上创建了一个非常简单的 Web 服务,每次调用它时,我都会使用数据源(在 conf/context 中定义)创建到数据库 (Oracle 12) 的连接.xml 文件)然后在将响应返回给客户端之前,它会关闭与数据库的连接。
但是如果我检查我的数据库上的活动会话,它会显示连接仍然存在,所以我有很多 "zombie" 连接到我的数据库。
我在客户端程序中使用了大致相同的代码,在这种情况下程序关闭了连接。也许是 Tomcat 错误的配置?
我该如何解决这个问题?
谢谢!
conf/context.xml
<Resource maxWaitMillis="5000"
maxIdle="100"
maxActive="200"
password="PASSWORD"
username="USER"
url="jdbc:oracle:thin:@/192.168.1.248:1521/PRD"
driverClassName="oracle.jdbc.driver.OracleDriver"
type="javax.sql.DataSource"
auth="Container"
name="jdbc_Connection"/>
Java
public String method() {
try {
System.out.println("---------------------------------------");
System.out.println("START");
System.out.println("---------------------------------------");
DataSource ds = (DataSource) InitialContext.doLookup("java:comp/env/jdbc_Connection");
Connection DB = ds.getConnection();
String sql ="SELECT VAR FROM TABLE_NAME";
PreparedStatement stmt = null;
try {
stmt = DB.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
while(rs.next()){
System.out.println("rs->"+rs.getString(1));
}
rs.close();
stmt.close();
} catch (SQLException ex) {
}finally{
if(stmt != null){
try {
stmt.close();
} catch (SQLException ex) {
}
}
}
System.out.println("CLOSE");
DB.close();
} catch (SQLException ex) {
ex.printStackTrace();
} catch (NamingException ex) {
ex.printStackTrace();
}
System.out.println("---------------------------------------");
System.out.println("END");
System.out.println("---------------------------------------");
return "HELLO";
}
他们不是僵尸。他们在连接池中等待重用。创建连接是昂贵的,所以你不想(真的)白白关闭它们。正如 Andreas 指出的那样,连接池 return 是一个包装连接,其中调用 close()
并没有真正关闭它。它只是 return 进入游泳池。
您的配置表明池中最多可以有 100 个空闲连接,总连接数为 200。正如马克所说,这可能是 way too much。