Неуправляемые потоки Spring Quartz Websphere Hibernate
-
05-07-2019 - |
Вопрос
Похоже, что наша реализация использования Quartz — JDBCJobStore вместе со Spring, Hibernate и Websphere создает неуправляемые потоки.
Я немного почитал и нашел техническую статью от IBM, в которой говорится, что использование Quartz со Spring приведет к этому.Они предлагают использовать CommnonJ для решения этой проблемы.
Я провел некоторые дальнейшие исследования, и единственные примеры, которые я видел до сих пор, касаются старого плана JobStore, которого нет в базе данных.
Итак, мне было интересно, есть ли у кого-нибудь пример решения этой проблемы.
Спасибо
Решение
У нас есть рабочее решение для этой проблемы (на самом деле два).
1) Измените исходный код кварца, чтобы использовать поток демона WorkManager в качестве основного потока планировщика.Работает, но требует замены кварты.Однако мы не использовали это, так как не хотели поддерживать взломанную версию кварца.(Это напомнило мне, что я собирался отправить это в проект, но совершенно забыл)
2) Создайте WorkManagerThreadPool, который будет использоваться в качестве пула потоков кварца.Реализуйте интерфейс для кварцевого ThreadPool, чтобы каждая задача, запускаемая в кварце, была заключена в общий объект Work, который затем будет запланирован в WorkManager.Ключевым моментом является то, что WorkManager в WorkManagerThreadPool должен быть инициализирован до запуска планировщика из потока Java EE (например, при инициализации сервлета).Затем WorkManagerThreadPool должен создать поток демона, который будет обрабатывать все запланированные задачи, создавая и планируя новые рабочие объекты.Таким образом, планировщик (в своем собственном потоке) передает задачи управляемому потоку (рабочему демону).
Это непросто, и, к сожалению, у меня нет кода, который можно было бы легко включить.
Другие советы
Добавляю еще один ответ в ветку, так как наконец-то нашел решение для этой проблемы.
Мое окружение:Была 8.5.5, Кварц 1.8.5, Пружины нет.
Проблема у меня был (указанный выше) неуправляемый поток, вызывающий исключение NamingException из ctx.lookup(myJndiUrl)
, который вместо этого корректно работал на других серверах приложений (JBoss, Weblogic);на самом деле Webpshere инициировал «инцидент» со следующим сообщением:
javax.naming.ConfigurationException:Операция JNDI с именем «java:» не может быть завершена, поскольку среда выполнения сервера не может связать поток операции с каким-либо компонентом приложения J2EE.Это условие может возникнуть, если клиент JNDI, использующий имя «java:», не выполняется в потоке запроса серверного приложения.Убедитесь, что приложение J2EE не выполняет операции JNDI над именами «java:» внутри статических блоков кода или в потоках, созданных этим приложением J2EE.Такой код не обязательно выполняется в потоке запроса серверного приложения и поэтому не поддерживается операциями JNDI над именами «java:».
Следующие шаги решили проблему:
1) обновлен до кварца 1.8.6 (без изменений кода), просто maven pom
2) добавил следующий параметр в путь к классам (в моем случае это папка EAR/lib), чтобы сделать доступным новый WorkManagerThreadExecutor
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-commonj</artifactId>
<version>1.8.6</version>
</dependency>
Примечание:в КТЗ-113 или официальная документация Quartz 1.х 2.х нет никакого упоминания о том, как активировать это исправление.
3) добавил следующее в кварц.свойства ("wm/default" был JNDI уже настроенного DefaultWorkManager в моем WAS 8.5.5, см. Ресурсы -> AsynchronousBeans -> WorkManagers в консоли WAS):
org.quartz.threadExecutor.class=org.quartz.custom.WorkManagerThreadExecutor
org.quartz.threadExecutor.workManagerName=wm/default
Примечание:правильный класс орг.кварц.обычай.WorkManagerThreadExecutor для кварца-планировщика-1.8.6 (проверено), или орг.кварц.общий j.WorkManagerThreadExecutor от 2.1.1 включено (не проверено, но проверено в реальных условиях кварцевые банки в репозиториях maven)
4) переместил Поиск JNDI в пустом конструкторе задания кварца (благодаря m_klovre «Поток вне контейнера J2EE»);то есть конструктор вызывался путем отражения (newInstance()
метод) из того же контекста J2EE моего приложения и имел доступ к java:global
пространство имен, в то время как execute(JobExecutionContext)
метод все еще работал в более плохом контексте, в котором отсутствовали все EJB моего приложения.
Надеюсь это поможет.
Пс.в качестве ссылки вы можете найти здесь пример файла кварца.properties, который я использовал выше
Проверьте эту статью:http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html
по сути, установите свойство TaskExecutor в SchedulerFactoryBean, чтобы использовать TaskExecutor org.springframework.scheduling.commonj.WorkManager, который будет использовать потоки, управляемые контейнером.
Просто примечание:приведенная выше ссылка на QUARTZ-708 больше не действительна.Эта новая проблема (в новой Jira) кажется для решения проблемы: http://jira.terracotta.org/jira/browse/QTZ-113 (fixVersion = 1.8.6, 2.0.2)
Вы можете проверить ссылку JIRA ниже, поднятую на кварце, по этому поводу.
http://jira.opensymphony.com/browse/QUARTZ-708
Здесь имеется необходимая реализация WebSphereThreadPool, которую можно использовать с упомянутыми изменениями в кварце.properties для удовлетворения ваших требований.Надеюсь это поможет.
С уважением, Шива
Вам придется использовать управляемые пулы потоков веб-сферы.Вы можете сделать это через Spring и commonj.CommonJ может иметь исполнителя задач, который будет создавать управляемые потоки.Вы даже можете использовать ссылку на ресурс управляемого потока jndi.Затем вы можете внедрить исполнитель задач commonj в Quartz SchedulerFactoryBean на основе Spring.
Пожалуйста, посмотри http://open.bekk.no/boss/spring-scheduling-in-websphere/ и перейдите к разделу «Кварц с CommonJ» для получения более подробной информации.
Предложение PaoloC для WAS85 и Quartz 1.8.6 также работает на WAS80 (и Quartz 1.8.6) и не требует Spring.(В моей настройке присутствует Spring 2.5.5, но он не используется в этом контексте.)
Таким образом, я смог переопределить SimpleJobFactory своим собственным вариантом, используя InjectionHelper для применения CDI к каждому вновь созданному заданию.Внедрение работает как для @EJB (с JNDI-поиском аннотированного удаленного бизнес-интерфейса EJB), так и для @Inject (с JNDI-поиском CDI BeanManager сначала с использованием нового InitialContext, а затем с использованием этого вновь полученного BM для поиска самого CDI-компонента).
Спасибо PaoloC за этот ответ!(Надеюсь, этот текст появится как «ответ PaoloC», а не как ответ на основную тему.Не нашел способа отличить их.)
Недавно я столкнулся с этой проблемой.Практически вам понадобится:
- Внедрите пул потоков, делегировав работу Websphere Work Manager.(Quartz предоставляет только SimpleThreadPool, который запускает задания в неуправляемых потоках).Скажите кварцу использовать этот пул потоков:
org.quartz.threadPool.class
свойство - Скажите кварцу использовать
WorkManagerThreadExecutor
(или реализовать собственный) с помощьюorg.quartz.threadExecutor.class
свойство - Немного терпения с громоздкими устаревшими веб-контейнерами :)
Вот демо на github использования Quartz с Websphere (а также Tomcat).
Надеюсь, это кому-то поможет..