CDI 2.0: Как проверить, сколько асинхронных событий, запущенных с помощью Event.fireAsync(), может выполняться одновременно
Я пишу веб-сервис REST с использованием Jersey, CDI 2.0 (реализация Weld 3.0.1. Final) и Tomcat. Цель веб-сервиса - запускать длинные вычислительные задачи, которые могут выполняться в течение нескольких минут или даже часов. Задача должна быть запущена с HTTP-запроса POST, отправленного веб-службе, однако запрос должен быть завершен немедленно и отправить ответ клиенту, в то время как запущенная задача должна выполнять свою работу в другом потоке.
Я уже решил это с помощью CDI 2.0 и его Event.fireAsync()
метод, позволяющий обрабатывать события асинхронно. Класс ресурсов JAX-RS, который обрабатывает POST-запросы, запускает асинхронное событие, которое затем обрабатывается методом асинхронного наблюдателя (аннотировано @ObservesAsync
) в отдельности @ApplicationScoped
Боб CDI.
Описанное решение прекрасно работает. Однако я заметил, что когда я одновременно запускаю несколько длинных задач в асинхронных событиях, только четыре из них фактически выполняются, а остальные находятся в очереди. Как только одно из четырех запущенных событий заканчивается, первое из событий в очереди начинает свою обработку.
Итак, мои вопросы:
- Как проверить, сколько потоков доступно для реальной асинхронной обработки событий CDI?
- Как проверить, сколько событий находится в очереди и ждать обработки в методе асинхронного наблюдателя?
1 ответ
По первому вопросу - по умолчанию будут использоваться доступные процессоры. Нечто подобное Runtime.getRuntime().availableProcessors() + 1
, Тем не менее, я полагаю, что вам нужны параметры конфигурации. Здесь вы можете выбрать, вы можете:
- Используйте конфигурацию сварного шва и выбирайте из заранее определенных опций
- Посмотрите на конфигурационную часть Weld doc
- Я бы предложил использовать
FIXED_TIMEOUT
пул (потоки не будут задерживаться, когда не нужны), ключ для этого конфигаorg.jboss.weld.executor.threadPoolType
- Вы можете установить желаемое количество потоков, используя клавишу
org.jboss.weld.executor.threadPoolSize
- Проверьте главу 19.1 о том, как передать параметры конфигурации в Weld
- Определите свой собственный
Executor
и запускать асинхронные события с помощьюNotificationOptions
- (OVERKILL) Реализуйте свой собственный
ExecutorServices
, часть Weld SPI
На ваш второй вопрос - я должен вас здесь разочаровать. В Weld пока нет способа достичь этого. Не стесняйтесь создавать проблему WELD Jira, и вы можете увидеть ее в будущем.