为什么我们的连接池关闭?

时间:2014-11-19 19:02:03

标签: java sql-server jsf tomcat connection-pooling

我们在Windows Server 2008 R2上运行的Apache Tomcat 7.0.54上运行了一个JSF2.0网络服务器。我们在运行它的机器上有2个SQL服务器,另一个托管我们的库存软件。我们网页的一部分是对要添加的PartNumbers的验证。在阅读了连接池是与SQL服务器交谈的最佳实践之后,我们创建了一个并使用它来对我们的库存软件进行一些验证。

因为我想要一种能够检查连接池健康状况的方法,所以我创建了一个带有ViewScoped辅助bean的测试页面,该辅助bean验证了2个已知的好的部件号。今天是本周第二次出现错误消息" Connection已关闭"出现了。由于我刚接触到泳池并且似乎无法找到有关此事的任何信息,我感到困惑的是我们没有正确设置。我刚刚重置Apache服务器,它已备份并运行。所以..为了创建我的连接池,我在应用程序的META-INF / context.xml中添加了一些代码。

    <Resource type="javax.sql.DataSource"
        name="jdbc/FOODB"
        factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
        driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
        url="jdbc:sqlserver://Foobar\Inventory;databaseName=FooInventory;user=johnDoe;password=astrongpassword;"
    />

我必须使用ConnectionPool的基本概念是我有一个名为SqlAccessCommand的接口。它或多或少是适配器模式。在我的测试页面中,我使用RunUnsafe方法,以便我可以显示错误消息。所以这是RunUnsafe方法。

protected static DataSource getDataSource() throws NamingException {
    Context context = (Context) new InitialContext().lookup("java:/comp/env");
    DataSource ds = (DataSource) context.lookup("jdbc/FOODB");
    return ds;
}
public static <T> T RunUnsafe(SqlAccessCommand<T> command) throws NamingException, SQLException {
    try {
        DataSource ds = getDataSource();
        try (Connection connection = ds.getConnection();
                PreparedStatement statement = connection.prepareStatement(command.getSqlStatement())) {
            command.prepareStatment(statement);
            try (ResultSet rs = statement.executeQuery()) {
                return command.getResults(rs);
            }
        }
    } catch (NamingException | SQLException e) {
        Logger.getLogger(AOSqlInformationHolder.class.getName()).log(Level.SEVERE, null, e);
        throw e;
    }
}

正如你所看到的,我使用try资源尝试在使用后关闭我的连接,无论如何。就像try / catch / finally一样,只是更干净(IMO)。所以当我的连接打开时,这很好用。到目前为止2x现在我不得不重新启动服务器(因为我不知道如何以任何其他方式重新打开所述连接)我错过了什么?如果需要更多部分拼图,请给我留言,我会发布我能做的。谢谢。

修改

只是查看了日志文件,今天早上发生了这个异常

com.microsoft.sqlserver.jdbc.SQLServerException:peer by peer:socket write error

根据迄今为止的评论,假设超时。此错误消息是否仍指向该方向?

3 个答案:

答案 0 :(得分:5)

您需要在连接池配置中添加一些 1 选项,以检测连接是否仍然有效。

最简单的方法是运行一个简单的SQL语句 2 来测试连接。

所以池配置可以是:

<Resource type="javax.sql.DataSource"
          name="jdbc/FOODB"
          factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
          driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
          url="jdbc:sqlserver://Foobar\Inventory;databaseName=FooInventory;user=johnDoe;password=astrongpassword;"
          validationQuery="SELECT 1"
          validationQueryTimeout="1000"
          testOnBorrow="true"
/>

备注

  1. 查看可用选项:The Tomcat JDBC Connection Pool
  2. Efficient SQL test query or validation query that will work across all (or most) databases

答案 1 :(得分:3)

根据您的 com.microsoft.sqlserver.jdbc.SQLServerException的日志消息,您的连接几乎肯定会由于不活动而超时:连接由peer重置:socket write error 您可以阅读此内容{ {3}}注意哪个,

  

连接被同伴强行关闭。这通常是由于超时或重启导致远程套接字上的连接丢失而导致的。

答案 2 :(得分:0)

我建议使用Abandon配置选项。

<Resource type="javax.sql.DataSource"
    name="jdbc/FOODB"
    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
    driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
    url="jdbc:sqlserver://Foobar\Inventory;databaseName=FooInventory;user=johnDoe;password=astrongpassword;"
    removeAbandoned="true"
        removeAbandonedTimeout="60"
        logAbandoned="true" 
/>