星期二, 一月 23, 2007

切记,资源需要关闭!

节前搭建起来的网站,由于业务的关系,暂时还没正式投入运行,访问量极低。就这样的背景下,居然隔三五天就不能访问了,甚至有一次3点还能访问,3点10分就访问不了啦,首页面可以出来,就是无法登录,查tomcat日志也什么都没有,蹊跷的很。
后来好好分析了一下,首页面是一个jsp页面,能够正常显示,应该是tomcat还活着,登录是一个servlet,其功能也很简单,就是到数据库里比一下口令。
既然jsp能出来,servlet不能响应,而jsp在运行的时候,也是转换为servlet在运行的,说明servlet的引擎也是好的,唯一的查找问题点就落在了数据库连接方面。
为了效率,在获取数据库连接方面使用了tomcat的连接池,难道是设置有不正确的地方?在网上搜集了很多这方面资料,也只有少量“瑕疵”而已,大体上还是正确的嘛。
最后还是把问题指向了连接池的关闭上。
昨天上午,好好查了一下代码,进行全文搜索,只要获取连接,看看后边有没跟一个关闭的语句。
果然就找到了,多个servlet就只有一个忘了关,他运行的次数越多,问题出现的也就越快!
原因太简单了,以前作项目也遇到过完全一样的问题,没想到还是不小心,漏关connection一次就造成这么明显的问题。
-------------------------------------------
附一个标准使用tomcat连接池的代码:
Here is an example of get db connection from a conectiono pool:
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
Connection conn = ds.getConnection();
//etc.

Here is an example of properly written code to use a db connection obtained from a connection pool:
Connection conn = null;
Statement stmt = null; // Or PreparedStatement if needed
ResultSet rs = null;
try {
conn = ... get connection from connection pool ...
stmt = conn.createStatement("select ...");
rs = stmt.executeQuery();
... iterate through the result set ...
rs.close();
rs = null;
stmt.close();
stmt = null;
conn.close(); // Return to connection pool
conn = null; // Make sure we don't close it twice
} catch (SQLException e) {
... deal with errors ...
} finally {
// Always make sure result sets and statements are closed,
// and the connection is returned to the pool
if (rs != null) {
try { rs.close(); } catch (SQLException e) { ; }
rs = null;
}
if (stmt != null) {
try { stmt.close(); } catch (SQLException e) { ; }
stmt = null;
}
if (conn != null) {
try { conn.close(); } catch (SQLException e) { ; }
conn = null;
}
}

没有评论: