Получение государственных акторов через рабочих акторов в AKKA

У меня есть три актера для обработки сценария CQRS. ProductWorkerActor обрабатывает часть команды, ProductQueryWorkerActor обрабатывает часть запроса, а ProductStateActor обрабатывает часть состояния.

Я обрабатываю запрос, используя:

ProductQueryWorkerActor.Ask<ProductState>("give-me-product-state-for-product-1000")

Код из ProductQueryWorkerActor:

if (message == "give-me-product-state-for-product-1000")
{
    var actor = Context.ActorSelection("akka://catalogSystem/user/productState/1000");
    var psDTO = actor.Ask<ProductStateDTO>(message).Result;
    Sender.Tell(ps);
}

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

  1. Должен ли я использовать Ask, как я использовал в этом случае, для получения состояния продукта? Ask называется фьючерсом?

  2. Должен ли я выставлять состояние как DTO для внешней работы, а не самого актера?

  3. Чтобы изменить какое-либо состояние продукта, должен ли я обрабатывать сообщения в ProductWorkerActor или в самом ProductStateActor? Во втором случае ProductWorkerActor отправляет сообщение ProductStateWorker, ProductStateWorker обрабатывает сообщение, изменяет состояние и отправляет другое сообщение ProductStateWorker. >ProductWorkerActor, что он прошел проверку и изменил состояние.


person wonderful world    schedule 19.05.2015    source источник


Ответы (1)


В случае, если вы используете Event Sourcing со своими актерами, я советую вам использовать Akka.Persistence. Он обрабатывает разделение субъектов чтения/записи и снимет с вас большую нагрузку.

Если нет, то, на мой взгляд, основная проблема вашего дизайна заключается в том, что, хотя у вас есть отдельные акторы для чтения/записи в состояние, само состояние обрабатывается только одним актером. Почему? Одним из пунктов CQRS является наличие отдельных моделей, оптимизированных для выполнения их роли (чтение или запись).

Например: у вас может быть один актор-обработчик (например, ProductActor), изменяющий свое состояние на основе входящих команд, и множество различных акторов только для чтения (например, ProductHistoryActor, ProductListActor), каждый со своим собственным состоянием, оптимизированным для их роль. Актеры только для чтения могут подписаться на поток событий, чтобы прослушивать входящие сообщения об изменениях состояния актера-обработчика и соответствующим образом обновлять свои собственные состояния, в то время как актор-обработчик после обработки команды публикует сообщение об изменении состояния, используя поток событий системы актора.

Объявление. 1: На мой взгляд, использование Ask для общения между актерами — это анти-шаблон. В вашем примере вы используете актор запроса для передачи сообщения актору состояния, а затем блокируете текущий актор до тех пор, пока не придет ответ (что очень плохо для производительности), просто чтобы отправить сообщение обратно отправителю. Вместо использования:

var psDTO = actor.Ask<ProductStateDTO>(message).Result;
Sender.Tell(ps);

вы могли бы просто написать:

actor.Forward(message);

и позвольте actor отправить ответ непосредственно отправителю (вашему актеру запроса не нужно участвовать в отправке ответа).

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

Объявление. 3: Я думаю, что в вашем примере различие между ProductWorkerActor и ProductStateWorker искусственно. Судя по тому, что вы показываете, они должны быть единым целым IMO.

person Bartosz Sypytkowski    schedule 19.05.2015
comment
Отличные ответы по пунктам 1 и 2. Я получил вдохновение разделить рабочего актера и государственного актера из книги Джейми Аллена Essential AKKA. В этом он предлагает разделять состояние и поведение. - person wonderful world; 19.05.2015
comment
'actor.Forward' не работает, потому что актор является ActorSelection. У ActorSelection нет расширения Forward. Я не уверен, как я могу получить основного актера из ActorSelection, чтобы я мог сделать Forward. - person wonderful world; 20.05.2015
comment
Форвард в основном эквивалентен Tell(message, Sender). Также будьте осторожны при работе с выбором актеров — их не следует использовать, если они действительно не нужны. Об этом есть лекция. - person Bartosz Sypytkowski; 20.05.2015