有没有办法让Akka.NET中给定节点上的所有实例化actor都可用

Max*_*ich 6 c# akka.net akka.net-cluster akka.net-networking

我在我的应用程序中有以下代码,它在我的集群中创建一个Akka.NET actor的实例:

_actorSystem = ActorSystem.Create("mycluster");
_actoraActor = this._actorSystem.ActorOf<ActorA>();
Run Code Online (Sandbox Code Playgroud)

请注意,我故意省略name属性,因为我打算创建类型为ActorA的N个actor,并且不想管理这些名称.运行上面我最后得到一个演员,其ID如下所示:

akka://mycluster/user/$a#1293118665
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是尝试从不同的节点确定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;
    }
}
Run Code Online (Sandbox Code Playgroud)

通过利用集群MEMBER-UP事件,我尝试向Identify新成员发送请求,但我遇到的问题是ClusterEvent.MemberUp提供的对象不包含有关节点内的actor的信息,但只显示包含如下所示的节点引用:

akka.tcp:// myCluster中@本地:666

这是完全有道理的,因为它已经上线的节点,而不是演员.

如果我更改我的代码以使用命名的actor:

_actorSystem = ActorSystem.Create("mycluster");
_actoraActor = this._actorSystem.ActorOf<ActorA>("actora");
Run Code Online (Sandbox Code Playgroud)

然后,我可以成功查询服务我需要的方式.这是您在拥有一个命名actor时所期望的,但似乎无法实际外部确定节点上正在运行的actor的实例.

因此,特别是当已经没有名字的使用产生的无名演员什么是正确的步骤来识别你感兴趣的角色引用的N个实例,当演员?

编辑:

我已经决定重申这个问题,因为我最初没有充分描述它.这个问题的正确表达是:

"当你所拥有的只是节点路径时,有没有办法让外部演员在给定节点上当前可用的所有实例化演员?"

对我来说,这似乎应该是基础框架内置的东西,除非有一些我不完全理解的设计考虑因素.

我还注意到,我认为我的特定问题的正确方法可能就是我正在尝试做Pub/Sub这个https://getakka.net/articles/clustering/distributed-publish-subscribe.html是更合适.

Aar*_*web 6

我认为出于您的目的,您应该考虑利用演员层次结构。

与其使用随机分配的名称创建顶级 actor,不如创建一个具有硬编码名称的父级:

_actorSystem = ActorSystem.Create("mycluster");
_delegatorParent = this._actorSystem.ActorOf<ParentActorA>("parent");
Run Code Online (Sandbox Code Playgroud)

这个父actor可以产生任意数量的子actor,它可以响应传入的消息产生子actor:

_delegatorParent.Tell(new WorkItem("someWork", 1200));
Run Code Online (Sandbox Code Playgroud)

这可能会导致父角色创建一个实际执行工作的子角色:

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

这为您提供了进入此节点/演员系列的固定入口点,同时仍然能够启动没有特定名称的新演员。只需查找具有静态名称的父项,而不是执行工作的子项。

当您在使用它时,您可能还想查看Akka.NET 中的池路由器和每个实体模式子项