Servlet stops working on Tomcat server after some

2019-07-12 20:42发布

问题:

I have a very strange issue with some of my servlets. Below is my configuration:

  • Folder A has X number of servlets deployed in Tomcat directory
  • Folder B has Y number of servlets deployed in Tomcat directory

After certain amount of time or hits to any of the servlets in Folder B, it stops working properly, whereas at same time all servlets of Folder A works fine.

I am not able to trace where I am doing mistake.

All coding for both folder's servlets is the same, the only difference is they are interacting with different DB's, but it is very simple read only operation with DB though.

Any ideas?

回答1:

The issue lies with the Logger. The Logger instance is not implicitly released when the thread finishes execution and since there is no obvious method such as close() to close the Logger instance, the doGet / doPost thread does not exit properly.

Getting rid of the Logger, or alternatively, explicitly destroying the instance / assigning it to null will solve the problem.



回答2:

Two important things to check in this kind of problems:

  1. Read the server logs for any exceptions and stacktraces. In Tomcat it's located in /logs folder. If you found any, then those should provide sufficient information to fix the problem yourself. But if you don't understand the cause, then you need to update your question to include the relevant exceptions and stacktraces. This way we can assist in explaining the cause so that the solution is obvious enough.

  2. Ensure that the code is not swallowing important exceptions anywhere. I.e. you need to at least rethrow or log them after catching. E.g. thus not:

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

    But more so:

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

    Or, at least:

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

    This way they will be logged to the server logs.

One of first things which comes to mind in your particular case is that the code is not closing database resources properly in finally block and the DB thus runs out of resources which leads to a failure in connecting, preparing statement and/or executing the query. With proper exception handling this should already be hinted in the server logs. Here's a basic kickoff example how to write JDBC code the proper way. The normal practice is to acquire and close the database resources in shortest possible scope:

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;
}

Any exception on close() can be ignored, but I prefer to log them so that you don't lost any evidence of a failure anywhere, even if it's minor.



回答3:

This could be a database time-out related issue. Maybe you're databases have different time-out times? Do you use connection pooling? (you should!) Is the pool setup identical for both connections? Are the databases configured to have time-out bigger than you're pool time-out values? Have you set autoReconnect=true in the connection parameter?