Как ограничить параллелизм при использовании актеров в Scala? - PullRequest
11 голосов
/ 22 февраля 2010

Я пришел с Java, где я бы отправил Runnable s в ExecutorService, поддерживаемый пулом потоков. В Java очень ясно, как устанавливать ограничения на размер пула потоков.

Я заинтересован в использовании актеров Scala, но мне неясно, как ограничить параллелизм.

Скажем гипотетически, что я создаю веб-сервис, который принимает "задания". Задание отправлено с POST запросами, и я хочу, чтобы моя служба поставила его в очередь, а затем немедленно вернула 202 Accepted - т.е. задания обрабатываются асинхронно.

Если я использую акторы для обработки заданий в очереди, как я могу ограничить число одновременных обрабатываемых заданий?

Я могу придумать несколько разных подходов к этому; Мне интересно, есть ли в сообществе лучшая практика или, по крайней мере, какие-то четко разработанные подходы, которые несколько стандартны в мире Scala.

Один из подходов, о которых я подумал, - это наличие одного актера-координатора, который управлял бы очередью заданий и субъектами обработки заданий; Я предполагаю, что он мог бы использовать простое поле int для отслеживания того, сколько заданий в настоящее время обрабатывается. Однако я уверен, что при таком подходе будут некоторые ошибки, такие как отслеживание ошибки при уменьшении числа. Вот почему мне интересно, предлагает ли Scala более простой или более инкапсулированный подход к этому.

Кстати, я пытался задать этот вопрос некоторое время назад , но я спросил его плохо.

Спасибо!

Ответы [ 3 ]

6 голосов
/ 22 февраля 2010

Я бы очень рекомендовал вам взглянуть на Akka, альтернативную реализацию Actor для Scala.

http://www.akkasource.org

Akka уже имеет интеграцию JAX-RS [1], и вы можете использовать ее совместно с LoadBalancer [2] для регулирования количества действий, которые можно выполнить в параллельном режиме:

[1] http://doc.akkasource.org/rest [2] http://github.com/jboner/akka/blob/master/akka-patterns/src/main/scala/Patterns.scala

5 голосов
/ 22 февраля 2010

Вы можете переопределить системные свойства actors.maxPoolSize и actors.corePoolSize, которые ограничивают размер пула потоков актера, а затем выбрасывать в пул столько заданий, сколько могут обработать ваши акторы. Почему вы думаете, что дроссель ваши реакции?

3 голосов
/ 23 февраля 2010

У вас действительно есть две проблемы здесь.

Первый - держать под контролем пул потоков, используемый актерами. Это можно сделать, установив системное свойство актеры. MaxPoolSize.

Вторым является стремительный рост числа задач, переданных в пул. Вы можете или не можете быть обеспокоены этим, однако вполне возможно вызвать условия сбоя, такие как ошибки нехватки памяти и в некоторых случаях потенциально более тонкие проблемы, генерируя слишком много задач слишком быстро.

Каждый рабочий поток поддерживает очередь задач. Исключение реализовано в виде массива, который рабочий поток будет динамически увеличивать до некоторого максимального размера. В 2.7.x очередь может вырасти довольно большой, и я видел, что триггеры из-за нехватки памяти объединяются с большим количеством одновременных потоков. Максимальный размер dequeue меньше 2.8. Также можно заполнить очередь.

Чтобы решить эту проблему, вы должны контролировать, сколько задач вы генерируете, что, вероятно, означает своего рода координатора, как вы обрисовали. Я столкнулся с этой проблемой, когда действующие лица, которые запускают своего рода конвейер обработки данных, намного быстрее, чем те, которые позже в конвейере. Чтобы контролировать процесс, я обычно заставляю актеров, которые позже в цепочке, возвращают актеров раньше в цепочке каждые X сообщений, а те, кто раньше в цепочке, останавливаются после сообщений Х и ждут ответа. Вы также можете сделать это с более централизованным координатором.

...