枚举 Akka.NET 集群中的可用参与者

Enumerating available actors in Akka.NET cluster

我有两个演员,我们称他们为 ActorA 和 ActorB。作为基于 Topshelf 的 Windows 服务,两个参与者都驻留在自己单独的进程中。

基本上他们看起来像这样。

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;
    }
}

我的配置文件超级简单

演员A:

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]
    }
}

演员B:

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 消息。但是,我可以使用相同的 ActorSelection 引用成功发送任何其他类型的消息 ActorA。

所以任何人都可以提供任何见解吗?为什么我的身份信息永远无法到达我的目标演员?

ActorIdentity message is invoked in ActorB rather than ActorA.

这按预期工作,因为您正在从参与者 B → A 发送 Identify 请求,ActorIdentity 是响应消息(从 A → B 自动发送)。

您已经可以观察到这种行为,因为:

Context.ActorSelection(path).ResolveOne(timeout)

或多或少相当于

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

Identify 是系统消息,它总是在调用任何程序员定义的消息处理程序之前处理 - 因此您可能不会在自己的处理程序中捕获它。