一些点击或时间后,Servlet停止在Tomcat服务器上工作

时间:2010-05-20 18:54:47

标签: java tomcat servlets jdbc

我的一些servlet有一个非常奇怪的问题。以下是我的配置:

  • 文件夹A在Tomcat目录中部署了X个servlet
  • 文件夹B在Tomcat目录中部署了多个servlet

经过一定的时间或点击文件夹B中的任何servlet后,它会停止正常工作,而同时文件夹A的所有servlet都能正常工作。

我无法追查我所犯的错误。

两个文件夹的servlet的所有编码都是相同的,唯一的区别是它们与不同的DB交互,但它只是对DB的非常简单的只读操作。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

问题在于Logger。当线程完成执行时,不会隐式释放Logger实例,并且由于没有明显的方法(如close()来关闭Logger实例),因此doGet / doPost线程无法正常退出。

删除Logger,或者显式地销毁实例/将其指定为null将解决问题。

答案 1 :(得分:0)

检查此类问题的两个重要事项:

  1. 读取服务器日志以查找任何异常和堆栈跟踪。在Tomcat中,它位于/logs文件夹中。如果您找到了,那么这些应该提供足够的信息来自行解决问题。但是如果您不了解原因,那么您需要更新您的问题以包含相关的异常和堆栈跟踪。通过这种方式,我们可以帮助解释原因,以便解决方案足够明显。

  2. 确保代码不会在任何地方吞下重要的例外情况。即你需要在捕获后至少重新抛出或记录它们。例如。因此

    try {
        // ...
    } catch (SQLException e) {
    }
    

    但更重要的是:

    try {
        // ...
    } catch (SQLException e) {
        throw new ServletException(e);
    }
    

    或者,至少

    try {
        // ...
    } catch (SQLException e) {
        e.printStackTrace();
    }
    

    这样他们就会被记录到服务器日志中。

  3. 在您的特定情况下首先想到的一件事是代码没有在finally块中正确关闭数据库资源,因此DB耗尽资源导致连接失败,准备语句和/或执行查询。通过适当的异常处理,这应该已经在服务器日志中提示。这是一个如何以正确的方式编写JDBC代码的基本启动示例。通常的做法是在尽可能短的范围内获取和关闭数据库资源:

    public List<Entity> list() throws SQLException {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        List<Entity> entities = new ArrayList<Data>();
    
        try {
            connection = database.getConnection();
            statement = connection.createStatement("SELECT id, name, value FROM entity");
            resultSet = statement.executeQuery();
            while (resultSet.next()) {
                Entity entity = new Entity(); 
                entity.setId(resultSet.getLong("id"));
                entity.setName(resultSet.getString("name"));
                entity.setValue(resultSet.getInteger("value"));
                entities.add(entity);
            }
        } finally {
            // Close in reversed order.
            if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
            if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
            if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
        }
    
        return entities;
    }
    

    close()上的任何异常都可以忽略,但我更喜欢记录它们,这样你就不会丢失任何失败的证据,即使它很小。

答案 2 :(得分:0)

这可能是数据库超时相关问题。也许你的数据库有不同的超时时间?你使用connection pooling吗? (你应该!)两个连接的池设置是否相同?数据库是否配置为超出池超时值的超时时间?您是否在连接参数中设置了autoReconnect = true?