Tomcat уничтожает слишком рано ServletContext при завершении работы? - PullRequest
0 голосов
/ 22 ноября 2018

При завершении работы я ожидаю, что Tomcat перестанет принимать новые запросы (и это делает!) И успешно завершит текущие запросы.К сожалению, ServletContext (Servlet.destroy, ServletContextListener.contextDestroyed, ...) уничтожается до завершения текущих запросов.Эти текущие запросы, основанные на ServletContext, не будут выполнены, и потенциально поврежденные данные !Контекст должен быть уничтожен только после обработки текущих запросов.

Погружаясь в код, метод org.apache.catalina.core.StandardService.stopInternal действительно показывает, что ServletContext уничтожается (оператор engine.stop()) перед закрытием (оператор connector.stop()) пула потоков длязапросы (ThreadPoolExecutor).

Я нашел параметр StandardContext.unloadDelay (Количество мс, что контейнер будет ожидать выгрузки сервлетов. Если не указано, значение по умолчанию составляет 2000 мс.), что может быть решением...

Знаете ли вы, как по-другому решить эту проблему?

Как воспроизвести:

@WebServlet(name = "StartStopServlet", displayName = "StartStopServlet", urlPatterns = "/execute")
public class StartStopServlet extends javax.servlet.http.HttpServlet {
    private ExpensiveResource resource = null;

    @Override
    public void init() throws ServletException {
        System.out.println("----> initializing StartStopServlet ...");
        super.init();

        resource = new ExpensiveResource();
        resource.connect();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // simulating time consuming operation before invoking ExpensiveService
        System.out.println("----> preparing parameters for ExpensiveResource call. It will take about 6 secs");

        // Now is the time to stop Tomcat: invoke shutdown.sh (or shutdown.bat)

        try {
            Thread.currentThread().sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // produces NullPointerException if ServletContext is destroyed
        Model result = resource.doWork();

        // Preparing response...
    }

    @Override
    public void destroy() {
        System.out.println("----> destroying StartStopServlet ...");
        super.destroy();

        resource.disconnect();
        resource = null;
    }
}

resource.doWork() оператор вызывается после destroy() метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...