Когда НЕЛЬЗЯ использовать актеров в акке / эрланге?

58

Я работаю с akka уже 7-8 месяцев ежедневно. Когда я начинал, я работал над приложениями и замечал, что актеры будут использоваться в любом месте внутри системы акторов для связи между большинством объектов. Я сделал то же самое - раскрутил другого актера за х / у / з.

Мне кажется, что это может быть слишком неразборчиво, добавляя сложность там, где это не нужно - но я не могу найти никаких дискуссий о том, где должны использоваться акторы против простой синхронной или даже асинхронной логики через фьючерсы. Я начал обдумывать свою позицию после того, как мой коллега упомянул нечто подобное. Совсем недавно я реализовал несколько случаев, когда я размышлял над задачей, а затем избегал создания другого действующего лица, потому что я мог бы безопасно достичь того же результата в неизменной реализации - например, что-то вроде получения значений конфигурации из БД или файла где-то, куда вы обращаетесь очень редко и дождаться результата - это фактический вариант использования.

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

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

JasonG
источник
Какая работа дает возможность работать с Akka ежедневно в течение нескольких месяцев?
День
3
Хорошие. :) Или внесите изменения самостоятельно.
JasonG
Я хотел бы знать конкретно, каковы компромиссы между askактером и просто использованием равнины Future.
Макс Хейбер
2
Я закончил тем, что написал книгу об Akka пару лет спустя, и я думаю, что вы можете подвести итог так: без синхронизации и блокировки. Если вы поместите это состояние в актера, внезапно вы можете быть уверены, что к нему безопасно обращаются, и вы не отбрасываете записи или не читаете устаревшие чтения. Актеры в erlang и akka также предполагают, что состояние может ухудшиться, и актер может выдавать ошибки, поэтому у вас есть некоторые характеристики системы самовосстановления. Фьючерсы проще, если вам не нужно мутировать
JasonG
много лет спустя я программист на эрланге / эликсире, и я продолжаю возвращаться к этому с новыми взглядами :) Эликсир совершенно другой, так как нет никаких объектов в качестве альтернативы процессам, поэтому процессы всегда создаются, когда вам нужно состояние . Это просто происходит одновременно. Это лучшая эвристика до сих пор.
JasonG

Ответы:

23

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

  • Я думаю, что Akka, потому что он работает с сообщениями, поощряет «настрой мышления». Часто для параллелизма я бы сказал, что это не то, что вы хотите. Тянуть намного безопаснее. Например, один общий шаблон для распределенных систем - это набор рабочих, обрабатывающих информацию в очереди . Очевидно, что это возможно в Akka, но это не обязательно первый подход, который люди пробуют . Akka также предлагает надежные почтовые ящики, но, опять же, это зависит от того, как вы их используете - единая общая очередь гораздо более гибкая, чем на рабочие очереди для балансировки / переназначения работы.
  • Легко войти в образ мыслей, заменяя свои классы актерами. На самом деле некоторые люди, кажется, даже защищают это, говоря, что актеры должны делать только одно . В соответствии с логическим заключением, это увеличивает сложность кода, как описывает Джейсон, потому что, если каждый класс является актером, это много дополнительных сообщений и блоков приема / отправки. Это также усложняет понимание и тестирование кода, потому что вы теряете формальность интерфейсов - и я не уверен, что комментарии являются решением этой проблемы . Кроме того, несмотря на легендарную эффективность Akka , я подозреваю, что распространение актеров не является хорошей идеей с точки зрения производительности - когда мы используем потоки Java, мы знаем, что они ценны и сохраняют их соответствующим образом.
  • Это связано с предыдущим пунктом, но еще одним раздражением является потеря информации о типах, которую выделяют Ноэль и Пино, поскольку для многих из нас именно поэтому мы используем Scala, а не другие языки, такие как Python. Есть несколько способов обойти это, но они либо нестандартные , не рекомендованные или экспериментальные .
  • Наконец, параллелизм, даже если у вас есть мышление «пусть разбивается» , сложно. Альтернативные модели программирования могут помочь, но они не заставляют проблемы уходить - они меняют их - поэтому хорошо думать о них формально . Именно поэтому разработчик Joe Average использует готовые инструменты, такие как базы данных RabbitMQ, Storm, Hadoop, Spark, Kafka или NoSQL. У Akka действительно есть несколько готовых инструментов и компонентов, и это здорово, но при этом ощущается довольно низкий уровень, поэтому более готовые встроенные общие элементы распределенных систем помогут разработчикам и обеспечат правильную сборку систем.

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

Марк Батлер
источник
1
Я нашел этот пост о тестировании в Akka на сайте timgilbert.wordpress.com/2013/07/07/…
Марк Батлер
«Композиция над наследованием» по-прежнему полезна для внедрения зависимостей. Например, передать зависимость в качестве реквизита (использует параметры конструктора). Тогда проблема будет в надзоре - созданный актер будет контролироваться где-то, кроме актера. Маршрутизатор можно использовать, чтобы обернуть стратегию надзора вокруг актеров, созданных на высшем уровне, но сейчас это довольно сложно! Я думаю, что торт был бы лучшим решением - например, иметь черту с созданием актера для актера службы БД. Затем просто используйте тестовую черту службы mock / stub db в текстовом контексте.
JasonG
1
Да, именно так - надзор плохо работает с внедрением зависимости. Также у меня были случаи, когда мне приходилось вводить фабрику, а не класс, в противном случае возникали странные проблемы с закрытием - наверное, из-за обработки потоков Akka.
Марк Батлер
Я думаю, что это не плохая идея - спасибо, спасибо - я мог бы попытаться написать об этом немного и пообщаться. Вы могли бы ввести что-то, что дает реквизит? Актерская фабрика актеров, где потребитель может создать экземпляр актера. Например, def method (arg) = return Props (new ActorWithArgs (arg)) из этой (psuedo?) фабрики, чтобы вы могли сделать актера в правильном контексте. Это кажется хорошей идеей и хорошей целью для решений для тортов для ди тоже.
JasonG
Я только начал следовать этому курсу: coursera.org/course/posa Хотя он в первую очередь предназначен для людей, программирующих на Android, он также является хорошим обзором параллелизма в Java. Одна вещь, которая меня интересует, такова: «Разве Akka не является просто причудливой формой циклов событий с некоторыми наворотами (потому что вы можете помещать циклы событий в разные потоки)?»
Марк Батлер
21

Стоит рассмотреть, для чего используется модель актера: модель актера

  1. модель параллелизма
  2. что позволяет избежать одновременного доступа к изменяемому состоянию
  3. использование асинхронных механизмов связи для обеспечения параллелизма.

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

  • Вы не разрешаете параллелизм, ИЛИ
  • Вы не допускаете изменяемое состояние (как в функциональном программировании), ИЛИ
  • Вы должны полагаться на какой-то механизм синхронной связи,

тогда модель актера не принесет много (если таковые имеются) выгоды.

Надеюсь, это поможет.

Эйдан Калли
источник
Спасибо. Думаю, вам действительно нужно оценивать две вещи: изменяемое состояние и параллелизм? Нет проблем для решения, если класс не имеет состояния ИЛИ не является параллельным. Еще одно соображение - я думаю, что отказоустойчивость это еще один момент? например, если у вас есть неизменяемый клиент Redis, но он может не работать во время работы - разве это не будет хорошим вариантом использования? что перезапуск этого актера может быть необходим? Поскольку - хотя класс может быть просто неизменным - вполне возможно, что поврежденное состояние будет внешним по отношению к неизменяемому действующему субъекту, что может привести к его провалу.
JasonG
Я полагаю, что актер, отвечающий за связь с Redis, получит исключение и перезапустится.
JasonG
@JasonG На мой взгляд, «отказоустойчивость» не является аспектом актерской модели в целом - это то, что идет с реализацией актерской модели в Erlang (и, может быть, Akka?). Я не могу говорить с Redis, хотя должен признать, что «неизменный клиент» звучит для меня странно ... Если программный компонент может выйти из строя, я не понимаю, как его можно считать неизменным.
Эйдан Калли
Отказоустойчивость и надзор существуют в akka, и это очень похоже на erlang. Я понимаю, что вы говорите об неизменяемом клиенте, но неизменность означает, что состояние кода нигде не меняется. Если я инициализирую соединение при запуске, вполне возможно, что клиентский код может быть неизменным с помощью стратегии перезапуска, используемой для любого рода ошибки, просто повторной инициализации субъекта при возникновении проблемы.
JasonG
12

Ваша интуиция верна, ИМХО. Повсеместно использовать актеров - все равно, что иметь молоток и видеть только гвозди.

Лучшая практика Erlang заключается в использовании процессов / действующих лиц для всех действий, которые происходят одновременно. То есть, как в реальной жизни. Иногда трудно найти правильную гранулярность, но в большинстве случаев вы просто знаете, взглянув на смоделированный домен и используя немного здравого смысла. Боюсь, у меня нет лучшего метода, чем этот, но я надеюсь, что это поможет.

Влад Думитреску
источник
Хорошо, спасибо. Мне действительно интересно посмотреть, что происходит в этой дискуссии.
Джейсон
0

В порядке ввода / вывода сообщений:

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

Проблема заключалась в том, что входящие сообщения перемещались по разным «дорожкам» (по разным путям актеров), но в коде предполагалось, что сообщения будут доставлены в конечный пункт назначения в том же порядке, в котором они поступили. До тех пор, пока данные поступали с достаточно большими интервалами, это работало, потому что в пункт назначения направлялось только одно противоречивое сообщение. Когда интервалы уменьшились, они начали выходить из строя и вызывать странное поведение.

Эту проблему можно было бы решить правильно с меньшим количеством актеров, но при злоупотреблении ими легко ошибиться.

ДГВ
источник
Это основополагающий и широко актуальный. Вы можете гарантировать заказ только между двумя актерами. doc.akka.io/docs/akka/current/scala/general/… Вы не можете гарантировать доставку заказа в любую систему, где вы разветвляетесь / входите . andreasohlund.net/2012/01/18/dont-assume-message-ordering
JasonG
-1

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

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

Такие базы данных, как mnesia, можно рассматривать как внешнее хранилище данных для процесса запросов.

Тони Уоллес
источник
1
Вы можете уточнить? Вы имеете в виду большое государство в сети? Внутри локального процесса передача ссылки на неизменяемую структуру практически не требует затрат, и вы не можете передать изменяемые структуры. Предполагая, что вы говорите о большой изменяемой структуре, которую нужно скопировать для отправки? Так что это в основном то же самое снова - общее состояние. Размер ничего не меняет. Дайте мне знать, если я неправильно понимаю.
JasonG
Так как вы проходите по ссылке? Конечно, способ сделать это состоит в том, чтобы поместить структуру в процесс и передать processid. Локальные вызовы поместят данные в стек, и каждый рекурсивный вызов сделает это снова (за исключением хвостовой рекурсии). Рекурсивная обработка структуры может быть выполнена с использованием списков для передачи состояния из одного вызова в другой, это состояние может затем ссылаться на структуру в другом процессе.
Тони Уоллес