Перечисление доступных актеров в кластере Akka.NET

У меня есть два актера, давайте назовем их ActorA и ActorB. Оба участника находятся в своем собственном отдельном процессе в качестве службы Windows на основе Topshelf.

В основном они выглядят так.

public class ActorA : ReceiveActor
{
    public ActorA()
    {
        this.Receive<ActorIdentity>(this.IdentifyMessageReceived);
    }


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

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"))
        {
            IActorRef actorSelection = await Context.ActorSelection("akka.tcp://mycluster@localhost:666/user/actora").ResolveOne(TimeSpan.FromSeconds(1));
            actorSelection.Tell(new Identify(1));
        }

        return true;
    }

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

Мои конфигурационные файлы очень просты

ActorA:

akka {
    log-config-on-start = on
    stdout-loglevel = DEBUG
    loglevel = DEBUG
    actor.provider = cluster
    remote {
        dot-netty.tcp {
            port = 666
            hostname = localhost

        }
    }
    cluster {
        seed-nodes = ["akka.tcp://mycluster@localhost:666"]
        roles = [actora]
    }
}

ActorB:

akka {
    log-config-on-start = on
    stdout-loglevel = DEBUG
    loglevel = DEBUG
    actor.provider = cluster
    remote {
        dot-netty.tcp {
            port = 0
            hostname = localhost
        }
    }
    cluster {
        seed-nodes = ["akka.tcp://mycluster@localhost:666"]
        roles = [actorb]
    }
}

Теперь я хочу идентифицировать всех заданных актеров, прикрепленных к моему кластеру. Я делаю это, ожидая узла кластера MEMBER UP событие и пытается отправить Identify() сообщение для данного актера, чтобы получить ссылку на него.

Проблема в том, что я не могу успешно отправить сообщение обратно ActorA, Фактически при выполнении вышеупомянутого кода (несмотря на то, что у меня есть правильная ссылка в методе ActorSelection), сообщение ActorIdentity вызывается в ActorB скорее, чем ActorA,

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

Так может ли кто-нибудь предоставить какое-либо понимание? Почему мое удостоверение личности никогда не достигает моего целевого актера?

1 ответ

Решение

Сообщение ActorIdentity вызывается в ActorB, а не в ActorA.

Это работает как задумано, так как вы отправляете Identify запрос от актера B → A, для которого ActorIdentity ответное сообщение (отправляется автоматически от A → B).

Вы уже можете наблюдать это поведение в действии, так как:

Context.ActorSelection(path).ResolveOne(timeout)

является более или менее эквивалентом

Context.ActorSelection(path).Ask<ActorIdentity>(new Identify(null), timeout: timeout)

Identify является системным сообщением, которое обрабатывается всегда до вызова любых определенных программистом обработчиков сообщений - по этой причине вы, вероятно, не поймаете его в своих собственных обработчиках.

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