代码之家  ›  专栏  ›  技术社区  ›  Maxim Gershkovich

是否有方法获取akka.net中给定节点上当前可用的所有实例化参与者

  •  6
  • Maxim Gershkovich  · 技术社区  · 7 年前

    我的应用程序中有以下代码,用于在集群中创建akka.net actor实例:

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

    注意,我故意省略name属性,因为我打算创建actora类型的n个actors,并且不想管理这些名称。运行上面的代码,我得到一个演员的ID如下所示:

    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@localhost:666

    这非常有意义,因为它是已经上线的节点,而不是演员。

    如果我将代码更改为使用命名演员:

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

    然后我可以成功地查询我需要的服务。当您有一个命名的actor时,这是您所期望的,但是似乎没有办法真正从外部确定节点上运行actor的实例。

    所以,当使用n个未命名的actors实例时,识别对您感兴趣的actors的引用的正确步骤是什么,特别是当actors是在没有名称的情况下生成的时候?

    编辑:

    我决定重提这个问题,因为我一开始没有充分地描述它。这个问题的正确表述是:

    “是否有方法获取当前可用的所有实例化参与者 一个来自外部参与者的给定节点,而您所拥有的只是节点路径?”

    在我看来,这应该是构建在基本框架中的东西,除非有某种设计考虑,我不完全理解。

    我还注意到,我认为解决我的特殊问题的正确方法可能是我试着做一个酒吧/酒吧 https://getakka.net/articles/clustering/distributed-publish-subscribe.html 更合适。

    1 回复  |  直到 7 年前
        1
  •  4
  •   Aaronontheweb    7 年前

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

    与其使用随机分配的名称创建顶级参与者,不如使用硬编码名称创建父对象:

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

    这给你一个固定的切入点进入这个节点/演员家庭,同时仍然有能力旋转新演员没有特定的名字。只要用静态名称查找父级,而不是执行该工作的孩子。

    当你在看的时候,你可能还想看看池路由器和 child per entity pattern in Akka.NET 是的。