我的应用程序中包含以下代码,该代码可在群集中创建Akka.NET actor的实例,例如:
_actorSystem = ActorSystem.Create("mycluster");
_actoraActor = this._actorSystem.ActorOf<ActorA>();
请注意,由于我打算创建ActorA类型的N个actor,并且不想管理名称,因此我故意省略了name属性。运行上面的代码,我得到一个演员,该演员的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");
然后我可以成功查询该服务的需求。这是当您拥有一个已命名的参与者时所期望的结果,但是似乎无法从外部实际确定节点上正在运行的参与者的实例。
因此,当使用N个未命名的actor实例时,正确的步骤是什么来标识对您感兴趣的actor的引用,特别是当生成的actor没有名称时?
编辑:
我已决定重述该问题,因为最初我没有充分描述它。这个问题的正确表达是:
“是否有一种方法可以使当前所有实例化的actor可用 当您拥有的全部是节点路径时,从外部参与者获得的给定节点?”
在我看来,这应该是基本框架中内置的内容,除非存在我不完全理解的某种设计注意事项。
我还注意到,我认为解决我的特定问题的正确方法可能只是我正在尝试进行发布/订阅,而这种https://getakka.net/articles/clustering/distributed-publish-subscribe.html更合适。
答案 0 :(得分:4)
我认为出于您的目的,您应该考虑利用参与者的层次结构。
创建一个具有硬编码名称的父级,而不是使用随机分配的名称创建顶级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。