Является ли Akka.net синхронным при обработке сообщений, не ждите в обработчике событий? - PullRequest
0 голосов
/ 06 ноября 2018

Насколько я понимаю, akka.net состоит в том, что сообщение обрабатывается по одному из его почтового ящика, оно не обрабатывает несколько сообщений одновременно для данного субъекта.

Что это означает с точки зрения использования ключевого слова await, я не думаю, что оно добавляет какую-либо ценность в мире шаблонов актеров.

Я понимаю, что akka.net решает проблемы с многопоточностью, позволяя вам создавать распределенные системы.

Обработчики событий ReceiveAsync, какова цель их использования? И есть ли необходимость использовать методы await и async в актере.

1 Ответ

0 голосов
/ 07 ноября 2018

Актерская модель Akka позволяет вам выражать асинхронные рабочие процессы как конечный автомат. Аналогичным образом компилятор C # создает код, отвечающий за обработку асинхронного / ожидающего кода. Так что да, вы можете создать полностью асинхронный код в Akka.NET, даже не используя async / await - большая часть akka.net внутренне работает так. В отношении ReceiveAsync следует помнить несколько моментов, самый большой из них касается повторного входа.

Реентерабельность

Я буду использовать здесь концепцию рабочего процесса - вы можете представить рабочий процесс как многошаговый процесс, который реализует какой-то запрос:

  1. В системах, основанных на сообщениях (например, Akka, но также и в NerviceBus Sagas или Azure Durable Functions) рабочий процесс может быть реализован как конечный автомат, представляющий собой комбинацию различных триггеров (сообщений) и блоков обработки (обработчиков сообщений).
  2. В async / await вы можете представлять триггеры как ожидающие, а блоки обработки - как части кода между одним вызовом await и следующим.

По умолчанию все действующие лица Akka являются реентерабельными - это означает, что когда вам приходится обрабатывать рабочий процесс, состоящий из множества шагов (довольно часто вы можете распознать их, используя Self.Tell(nextStepSignal)), он может тем временем принимайте новые входящие запросы просто потому, что нет различий между сообщением, начинающим новый рабочий процесс, и тем, которое сигнализирует о следующем шаге рабочего процесса, который уже выполняется. Таким образом, по сути актер может выполнять множество параллельных рабочих процессов, в то же время обрабатывая каждый блок в одном потоке.

Хотя это полезное свойство в большинстве случаев, иногда вы хотите, чтобы актер находился в фиксированном состоянии в течение всего времени, необходимого для обработки рабочего процесса. При использовании стандартного подхода в Akka это может быть достигнуто как комбинация скрытия и изменения поведения Become / Unbecome - мы меняем поведение актера и начинаем хранить сообщения, не связанные с этим поведением, и после завершения рабочего процесса мы возвращаемся к предыдущему поведению и распаковка ожидающих сообщений.

Разница в ReceiveAsync заключается в том, что актер не возвращается, пока обработчик асинхронных сообщений не завершит . Как это достигается? Проще говоря, почтовый ящик актера приостанавливается до тех пор, пока обработчик не вернет результат. Это означает, что за это время актер не будет обрабатывать новые сообщения. Это имеет несколько плюсов и минусов.

Плюсы:

  • В основном это легко использовать с существующими библиотеками .NET. Вместо того, чтобы создавать свой собственный конечный автомат, вы позволяете компилятору C # генерировать его собственный.
  • Вы знаете, что состояние актера не будет изменено никакими другими рабочими процессами, выполняемыми параллельно.
  • Вам не нужно копить, чтобы держать вещи вокруг. Иногда это полезно в сочетании с другими функциями, такими как опция маршрутизатора SmallestMailbox: , поскольку при сборе происходит выборка элементов из почтового ящика актера, он будет получать все больше и больше сообщений (как тот, который имеет самый маленький почтовый ящик), даже если вы этого не делаете обработать их .
  • В некоторых случаях отладки вы получаете четкие следы стека.

Минусы:

  • Поскольку актер не может обрабатывать другие запросы, у него ограничены возможности общения с другими актерами. То есть вы все еще можете использовать Ask для других участников, но это более дорогой вариант, чем Tell обмен сообщениями.
  • В общем, актеры Akka оптимизированы, чтобы использовать в своих интересах модель повторного входа, и использование ReceiveAsync считается более медленным вариантом. Однако вам нужно принять собственные меры, чтобы решить, какая скорость вас устраивает.
  • Поскольку субъект не является повторно входящим, он не будет обрабатывать новые сообщения, пока текущий рабочий процесс не завершится. Это означает, что субъект не может обрабатывать какие-либо новые сообщения, потому что он ожидает истечения времени ожидания (или ожидает вечно, если вы не указали время ожидания).
  • При отладке компонента с состоянием (например, актера) конечный автомат с ручной настройкой может сказать вам больше, чем трасса стека длиной в милю: просто потому, что трассировки стека мало говорят о реальном состоянии компонента, который упал.
...