2017-01-14 20 views
1

Я начинаю искать рамку Akka.Net с загрузочным лагерем.Akka.Net Публикация и подписка на доменные события

Я смог понять основную концепцию и упорство актера с использованием источников событий.

Я застрял в понимании того, как событие домена будет отправлено и получено другими участниками.

Ограничение на одной системе локально развернутые Актёры и никакие DI контейнеры и Использование C# /ASP.NET API, где я отделяющий каждый AgreegateRoot в свой собственный проект

Я концептуализации что-то вроде

  • ManagerActor

    • -AggregateRoot
      • --ChildActor 1
      • --ChildActor 2
      • --ChildActor н
    • -ValidationActor

менеджер Актер получит сообщение с командой и пройти через процесс проверки и если подтвержденный будет отправлен актеру AggregateRoot. Событие будет создано внутри корневых или дочерних актеров.

пожалуйста посоветуйте на следующее:

Чтобы опубликовать событие на что-то подобное eventbus из внутри Субъект я могу использовать приведенный ниже синтаксис?

Context.System.EventStream.Publish(MyEvent); 

Чтобы подписаться на событие я понял, что синтаксис

System.EventStream.Subscribe(subscriber,MyEvent) 

Я хочу, чтобы событие опубликовал Актером быть обработаны обработчиком (другие актеры), из которых ток AggregateRoot Актер или Child Entity внутри не должны знать.

Здесь я полностью застрял. Как это достигается?

подписчик в System.EventStream.Subscribe, IActorRef. Чтобы получить это, мне понадобится знание класса.

Должен ли я создать загрузочный загрузочный автозагрузчик, который будет ссылаться на все проекты/AggregateRoots и строить Подписки на типы сообщений там?

Я пытался найти блоги или рецензии, но не имел большой удачи.

Спасибо заранее.

ответ

0

Я отделяя каждый AgreegateRoot в свой собственный проект

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

Похоже, что вы можете запутаться в том, как ссылаться на типы C#, которые представляют ваши события, что неудивительно, если у вас есть отдельный проект на AggregateRoot - вы быстро столкнетесь с круговыми ссылками. Попробуйте начать с одного проекта, в котором вы разделяете ограниченные контексты с помощью папок. В каждой папке создайте любые необходимые вам агрегаты и любые события, за которые они отвечают. Таким образом, все участники могут видеть все типы событий. После этого растет/становится неуправляемым вы можете посмотреть на разделив его на отдельные проекты, что-то вдоль линий:

  • MyApp.BoundedContext1
  • MyApp.BoundedContext1.Events
  • MyApp.BoundedContext2
  • MYAPP .BoundedContext2.Events

Обратите внимание, что события, которые ваши актеры создают и подписываются, представляют собой своего рода публичный контракт/API по всей системе. Наличие их как отдельных DLL, как описано выше, позволяет избежать циклических ссылок (поскольку проект .Events ничего не ссылается). Таким образом, в этой структуре MyApp.BoundedContext1 может иметь ссылку на MyApp.BoundedContext1.Events и опубликовать их. MyApp.BoundedContext2также может ссылаться на MyApp.BoundedContext1.Events и подписаться на них.

Я хочу, чтобы событие, опубликованное актером, обрабатывалось обработчиками (другими актерами), из которых действующий Акционерный агрегат или Детское Существо внутри не должен знать.

Здесь я полностью застрял. Как это достигается?

Ваш издатель не нуждается в знании подписчиков. Издатель просто публикует сообщение в EventStream. Контекст, в котором определены как актер, так и тип события, должен быть одинаковым (то есть издатели должны «владеть» их типами событий). Например, если у вас есть ValidationActor, который публикует события ThingValidated, они должны быть в одном контексте.

подписчик в System.EventStream.Subscribe, IActorRef. Чтобы получить это, мне понадобится знание класса.

Какой класс? Абонент уже знает о себе. Вы можете просто использовать Self, чтобы получить IActorRef. Если вы имеете в виду класс , то см. Выше о том, как структурировать проект для ссылки на него.

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

+0

Получаю, что «как только актер создан, он может регистрироваться для любых типов событий, в которых он заинтересован», но что, если Актер не создан. Допустим, актер, которому необходимо подписаться на событие, обрабатывает событие для хранения данных в Read Database. Я бы не хотел создавать экземпляр этого Актера, прежде чем он должен обработать событие. И если он актер не создан Контекст. System.EventStream.Subscribe (self, MyEvent) не будет достигнута. - Должен ли я активировать всех участников Менеджера при запуске приложения? – TheMar

+0

Почему бы вам не создать экземпляр, прежде чем он понадобится? Откуда вы знаете, когда это потребуется? почему бы просто не создать его при запуске? Они используют крошечный объем памяти, если просто сидят в ожидании события. – tomliversidge

+0

Том, спасибо, может быть, как вы сказали, я делал перехитрить, слишком много думая о удаленных развертываниях и осколках. Спасибо, что поделились своими знаниями. Он начнет меня на POC – TheMar

1

Другим решением является использование Akka.Cluster.Sharding, которое идеально подходит для этого прецедента. Однако; Я соглашусь, что кластерное окошко не является новичком. Clard sharding позволяет вам настроить, как ваш актер будет создан через реквизиты, а также стратегию для сопоставления сообщений конкретному «Entity».

Вот пример настройки кластера шардинге для актера из примера в блоге я связан с выше:

using(var system = ActorSystem.Create("cluster-system")) 
{ 
    var sharding = ClusterSharding.Get(system); 
    var shardRegion = sharding.Start(
     typeName: nameof(MyActor), 
     entityProps: Props.Create<MyActor>(), // the Props used to create entities 
     settings: ClusterShardingSettings.Create(system), 
     messageExtractor: new MessageExtractor(maxNumberOfNodes * 10) 
    ); 

    // ... etc 
} 

И вы могли бы затем отправить сообщение, как это:

region.Tell(new ShardEnvelope("<entity-id>", new MyMessage())); 

Message Extractor

Выделитель сообщений, упомянутый выше, является ключевым компонентом при выполнении этой работы. Экстрактор сообщений позволяет отображать сообщение в конкретный объект (фактически entityId). Поэтому, если ваши сообщения, например, имеют в них идентификатор целевого объекта, то это становится простым. Вот экстрактор пример сообщения (еще раз с поста petabridge блога и кодовой базы Akka.Net):

public sealed class MessageExtractor : HashCodeMessageExtractor 
{ 
    public MessageExtractor(int maxNumberOfShards) : base(maxNumberOfShards) { } 
    public override string EntityId(object message) => 
     (message as ShardEnvelope)?.EntityId; 
    public override object EntityMessage(object message) => 
     (message as ShardEnvelope)?.Payload; 
} 

public sealed class ShardEnvelope 
{ 
    public readonly string EntityId; 
    public readonly object Payload; 

    public ShardEnvelope(string entityId, object payload) 
    { 
     EntityId = entityId; 
     Payload = payload; 
    } 
} 

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

+0

Thanks , Выглядит больше, в соответствии с тем, что мне нужно. Я даже не смотрел на Шардинга. Я дам ему попробовать. Интересно, как пользователи, пытающиеся перейти с DDD на AKKA.net, оценивают/работают. – TheMar

 Смежные вопросы

  • Нет связанных вопросов^_^