Есть ли способ получить все созданные экземпляры действующих лиц в настоящее время доступны на данном узле в Akka.NET

У меня есть следующий код в моем приложении, который создает экземпляр актера Akka.NET в моем кластере как таковой:

_actorSystem = ActorSystem.Create("mycluster");
_actoraActor = this._actorSystem.ActorOf<ActorA>();

Обратите внимание, что я намеренно опускаю свойство name, поскольку намереваюсь создать N акторов типа ActorA и не хочу управлять именами. Запустив вышеизложенное, я получаю актера с идентификатором, который выглядит следующим образом:

akka://mycluster/user/$a#1293118665

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

public class ActorB : ReceiveActor
{
    private readonly Cluster Cluster = Akka.Cluster.Cluster.Get(Context.System);


    public ActorB()
    {

        this.Receive<ActorIdentity>(this.IdentifyMessageReceived);
        this.ReceiveAsync<ClusterEvent.MemberUp>(this.MemberUpReceived);
    }

    protected override void PreStart()
    {
        this.Cluster.Subscribe(this.Self, ClusterEvent.InitialStateAsEvents, new[]
        {
            typeof(ClusterEvent.IMemberEvent),
            typeof(ClusterEvent.UnreachableMember)                
        });
    }

    protected override void PostStop()
    {
        this.Cluster.Unsubscribe(this.Self);
    }

    private async Task<bool> MemberUpReceived(ClusterEvent.MemberUp obj)
    {
        if (obj.Member.HasRole("actora"))
        {
            //!The problem is here.
            //ALL YOU ARE PROVIDED IS THE NODE ADDRESS:  
            //Obviously this makes sense because it's the node that has come alive
            //and not the instances themselves.

            string address = obj.Member.Address.ToString();
            //akka.tcp://mycluster@localhost:666
            Context.ActorSelection(address).Tell(new Identify(1));
        }

        return true;
    }

    private bool IdentifyMessageReceived(ActorIdentity obj)
    {
        return true;
    }
}

Где через использование кластера MEMBER-UP событие, которое я пытаюсь отправить Identify запрос к новому члену, но проблема, с которой я сталкиваюсь, заключается в ClusterEvent.MemberUp Предоставленный объект не содержит информацию об актерах в узле, а только содержит ссылку на узел, которая выглядит следующим образом:

akka.tcp: // mycluster @ локальный:666

Что имеет смысл, потому что это узел, который подключился к сети, а не актер.

Если я изменю свой код для использования именованного актера:

_actorSystem = ActorSystem.Create("mycluster");
_actoraActor = this._actorSystem.ActorOf<ActorA>("actora");

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

Итак, при использовании N экземпляров неназванных актеров, каковы правильные шаги для определения ссылок на актеров, которые вас интересуют, особенно когда актеры были сгенерированы без имени?

РЕДАКТИРОВАТЬ:

Я решил переформулировать вопрос, потому что изначально не описал его адекватно. Правильное выражение этого вопроса:

"Есть ли способ получить все экземпляры действующих экземпляров, доступные в данный момент на данном узле, от внешнего субъекта, когда у вас есть только путь к узлу?"

Мне просто кажется, что это должно быть что-то встроенное в базовую платформу, ЕСЛИ У меня есть некие конструктивные соображения, которые я не до конца понимаю.

Я также отмечаю, что, вероятно, правильный подход к моей конкретной проблеме может заключаться в том, что я пытаюсь создать Pub/Sub, и этот https://getakka.net/articles/clustering/distributed-publish-subscribe.html более подходящий.

1 ответ

Решение

Я думаю, что для ваших целей здесь вы должны рассмотреть возможность использования иерархии актеров.

Вместо создания актера верхнего уровня со случайно назначенным именем создайте родителя с жестко заданным именем:

_actorSystem = ActorSystem.Create("mycluster");
_delegatorParent = this._actorSystem.ActorOf<ParentActorA>("parent");

Этот родительский актер может порождать любое количество детей, и он может порождать детей в ответ на входящие сообщения:

_delegatorParent.Tell(new WorkItem("someWork", 1200));

Это может привести к тому, что родительский объект создаст дочерний актер, который фактически выполняет работу:

public class ParentActorA{
    public ParentActorA(){
       Receive<WorkItem>(x => {
          // create new child to carry out the work
          var delegatorActor = Context.ActorOf<ActorA>();
          delegatorActor.Forward(x);
       });
    }
}

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

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

Другие вопросы по тегам