Threadpool Deadlock: проектирование против или обнаружения
Я надеюсь, что это не слишком широко; У меня вопрос: "Как мне спроектировать сервис с несколькими пулами потоков, который не может заблокировать сам себя?".
У меня есть веб-сервис, который разветвляет до сотен потоков по запросу одного пользователя для агрегирования данных с малой задержкой. Существует множество ExecutorServices, обертывающих пулы с фиксированными потоками, разбросанных по всему моему сервису, и мне нужна помощь в поиске интересного способа, который может создать тупик.
У меня есть пул A
который используется для хранения потоков, делающих сетевые запросы, и другого пула потоков B
который используется для хранения их "владеющих" потоков; агрегационные биты бизнес-логики, которые могут распадаться на несколько запросов. Кроме того, темы в B
иногда отправлять кусочки работы в пул потоков B
когда агрегация может быть выполнена путем агрегирования 3 более простых субагрегаций.
Эта модель является проблемой. Давайте рассмотрим стиль запроса x
представлен B
что вызывает дополнительный запрос x'
быть представленным B
, Давайте также рассмотрим B
фиксированный пул из 50 потоков. Когда 50 запросов типа x
зайти одновременно, все темы B
используются для обработки этих запросов. Все они представляют свои x1
в B
, который сидит в очереди в ожидании потока. Затем вся обработка всех запросов заходит в тупик на 60 секунд, пока не истечет время ожидания, и x
просит все возвратные исключения.
Вещи, которые я рассмотрел / попробовал:
- Твик номера. Максимальное количество пользователей, которые могут подключиться, составляет 50, потоков в
B
100. Предотвращает проблему, но кажется хаком, который сломается, когда другой разработчик подправит несвязанные числа через год, и никто не сможет понять, почему мы блокируемся один раз в неделю под нагрузкой. Я хочу решить это в дизайне. B
подчиняет раздутую работуB'
новый пул потоков. Не работает, потому что этот разветвление может пройти несколько этапов (создатьB''
,B'''
,...?)B
не имеет максимальных потоков. Возможно, приемлемо, кажется опасным.- Другая модель (более обратная?), Где потоки не отправляют и не ждут той же единицы работы; скорее они отправляют работу и отправляют "обратный вызов" в пул "run-after". Таким образом, ничто не может ждать чего-то в своем собственном пуле. Есть ли прецедент, это хорошая идея?
- Свернуть все пулы потоков вместе и удалить максимум?
1 ответ
Ваш "более обратный" ответ выглядит так, как будто он в основном решается за вас через API CompletionStage в Java 8 - отсутствие метода runAfterAllAsync означает, что вам, возможно, придется выполнить некоторую внешнюю работу, чтобы что-то произошло после того, как ваша группа 3 подзадачи, но именно здесь я бы начал искать. В этом уроке есть пример, который может помочь.