Должны ли Akka Actors выполнять реальные задачи обработки?

Я пишу приложение, которое читает относительно большие текстовые файлы, проверяет и преобразует данные (каждая строка в текстовом файле является собственным элементом, имеется около 100 миллионов элементов в файле) и создает какой-то вывод. Уже существует многопоточное Java-приложение (использующее BlockingQueue между чтением / обработкой / сохранением задач), но я хочу реализовать приложение Scala, которое делает то же самое.

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

В нескольких документах говорится, что Актеры никогда не должны блокироваться, и я понимаю, почему. Но в приведенных примерах для кода блокировки всегда упоминаются только такие вещи, как блокировка ввода-вывода файлов / сети ... вещи, которые заставляют актера ждать в течение короткого периода времени, что, конечно, плохо.

Но что, если актер «блокирует», потому что на самом деле он делает что-то полезное, а не ждет? В моем случае обработка и преобразование одной строки / элемента текста занимает 80 мс, что довольно долго (чистая обработка, без операций ввода-вывода). Может ли эта работа выполняться актером напрямую или я должен использовать Future вместо этого (но тогда, если мне все равно придется использовать Futures, зачем вообще использовать Akka ...) ?.

Документы и примеры Akka показывают, что актеры могут выполнять работу напрямую. Но кажется, что авторы делают только очень упрощенную работу (например, вызывают фильтр в строке или увеличивают счетчик и все). Я не знаю, делают ли они это для того, чтобы документы оставались простыми и лаконичными, или потому, что вам действительно не следует делать больше этого внутри актера.

Как бы вы спроектировали приложение на основе Akka для моего варианта использования (чтение текстового файла, обработка каждой строки, что занимает довольно много времени, в конечном итоге сохранение результата)? Или это какая-то проблема, не подходящая для Акки?


person alapeno    schedule 14.09.2015    source источник
comment
блокирование Future внутри общего пула потоков не рекомендуется, так как это также вызывает нехватку потоков. 80 мс для реальных вычислений - это нормально, так как это более-менее стабильное значение, вы можете использовать процессор на полную мощность   -  person dk14    schedule 14.09.2015
comment
вы также можете рассмотреть возможность разделения вычислений на более мелкие части и делегировать их другим участникам.   -  person Ihor Kaharlichenko    schedule 14.09.2015


Ответы (2)


Все зависит от типа актера.

Я использую это эмпирическое правило: если вам не нужно разговаривать с этим актером и у этого актера нет других обязанностей, то можно заблокировать его выполнение реальной работы. Вы можете относиться к нему как к Future, и это то, что я бы назвал «рабочим».

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

Есть несколько шаблонов, которые включают в себя вытягивание / выталкивание работы или модель актора на запрос. Любой из них может подойти для вашего приложения. У вас может быть менеджер, который создает актера для каждой части работы, и когда работа завершена, актер отправляет результат обратно менеджеру и умирает. Вы также можете сохранить жизнь актеру и попросить у него больше работы. Вы также можете комбинировать актеров и Futures.

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

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

Заявление об отказе от ответственности: под блокировкой я подразумеваю выполнение реальной работы, а не просто ожидание, которое никогда не бывает нормальным.

person yǝsʞǝla    schedule 14.09.2015
comment
Спасибо, это имеет для меня смысл. Однако мне интересно, не важно ли знать, сколько базовых потоков задействовано. Представьте, у вас очень отзывчивый актер, который распределяет всю работу и совсем не блокирует. Затем есть актер-исполнитель, который получает работу и блокирует ее выполнение на определенное время. На первый взгляд такой сценарий кажется нормальным. Но что, если оба участника работают в одном потоке? Разве рабочий актер не замедлит актера распределения, пока есть над чем поработать? И если да, то можно ли это контролировать? - person alapeno; 25.09.2015
comment
У вас могут быть отдельные пулы потоков или контексты выполнения для отдельных групп субъектов: doc .akka.io / docs / akka / snapshot / scala / dispatchers.html. - person yǝsʞǝla; 25.09.2015

Для актера нормально выполнять вычисления, которые занимают 100 мсек. Тем не менее, вы должны убедиться, что правильно справились с противодавлением. Один из способов - использовать шаблон выполнения работы, когда ваш процессор ограничен акторы запрашивают новую работу всякий раз, когда они готовы, вместо того, чтобы получать новые рабочие элементы в сообщении.

Тем не менее, описание вашей проблемы звучит как конвейер обработки, который может выиграть от использования абстракции более высокого уровня, такой как потоки akka. По сути, создайте поток имен файлов для обработки, а затем используйте преобразования, такие как map, для получения желаемого результата. У меня есть что-то подобное в производстве, которое звучит очень похоже на ваше описание проблемы, и оно работает очень хорошо при условии, что данные, используемые отдельными фрагментами обработки, не слишком велики.

Конечно, поток также будет материализован для ряда участников. Но высокоуровневый интерфейс будет более безопасным по типу, и о нем будет легче думать.

person Rüdiger Klaehn    schedule 14.09.2015