Мы находимся в процессе миграции нашего приложения с Websphere на Tomcat. Я заметил одну вещь: когда я выдаю shutdown.sh
для Tomcat процесс все еще продолжается. Сначала я думал, что процесс завершится через минуту или две, но даже через 5 минут я все еще вижу процесс живым. Поэтому мне нужно убить процесс, используя kill -9
а потом для начала.
При выключении я вижу много ошибок, которые появляются на консоли, например:
org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [some_application] appears to have started a thread named [Timer-0] but has failed to stop it.
Код состоит из веб-приложений, которые представляют собой смесь сервлетов, пружины и целой группы потоков, запускаемых при загрузке приложения.
Есть ли что-то, что я могу сделать с точки зрения конфигурации, чтобы решить эту проблему? Или для этого требуется некоторая доработка кода, чтобы компенсировать то, что WebSphere предоставляет "из коробки"?
Подобные проблемы лучше всего решать с помощью кода.
Хотя вы можете использовать catalina.sh stop -force
чтобы завершить работу экземпляра Tomcat, несмотря ни на что, дело в том, что Tomcat считает, что эти потоки выполняются по какой-то причине, и завершение ваших потоков может оставить ваше приложение в несогласованном состоянии (например, если оно завершено на полпути к записи чего-либо).
Если вы точно знаете, что такого не может быть, используйте -force
переключаться при остановке Tomcat.
Однако лучше всего написать приложение так, чтобы оно либо отмечало потоки как демоны (путем вызова setDaemon(true)
на Thread
instance), поэтому они могут быть завершены всякий раз, когда виртуальная машина закрывается, или (если потоки не должны быть убиты в любое время) зарегистрировать ловушку отключения, реализовав ServletContextListener
, и выполнение рутинных работ по завершению работы в contextDestroyed
метод. Вот это вопрос по StackOverflow об установке ловушки выключения.
Ваше приложение, вероятно, оставляет кучу не-демон потоки запущены, поэтому он никогда не завершится.
Тема, которую вы упомянули в своем вопросе, - это TimerThread
и Tomcat знает, как их (почти) безопасно выключить. Просто добавь clearReferencesStopTimerThreads="true"
в контексте вашего приложения:
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="yourAppName"
clearReferencesStopTimerThreads="true" />
Однако, как упомянул Лачек, правильный способ справиться с ними - это ServletContextListener
или другой механизм для администрирования Thread
жизненный цикл. Поскольку вы используете контейнер Spring, я бы добавил Диспетчер задач (<task:scheduler id="" pool-size="" />
) на ваш ApplicationContext
и внедрить его в каждый компонент, для которого требуется планирование задачи. Если вашим сервлетам нужно планировать задачи, создайте ScheduledExecutorService в ServletContextListener
и сохраните ссылку на него в ServletContext
.
PS: также есть clearReferencesStopThreads
атрибут, но описание в Руководство по настройке Apache Tomcat должен дать вам подсказку, когда его использовать:
Если true, Tomcat пытается завершить потоки, запущенные веб-приложением. Остановка потоков выполняется с помощью устаревшего (по уважительной причине) метода Thread.stop () и, вероятно, приведет к нестабильность. Таким образом, включение этого параметра следует рассматривать как вариант Крайнее средство в среде разработки и не рекомендуется в производственной среде. Если не указано, будет использоваться значение по умолчанию false. Если эта функция включена, веб-приложениям может потребоваться до двух секунд для остановки, поскольку потокам-исполнителям дается до двух секунд для корректной остановки перед вызовом Thread.stop () для всех оставшихся потоков.