Есть ли способ получить все созданные экземпляры действующих лиц в настоящее время доступны на данном узле в Akka.NET
У меня есть следующий код в моем приложении, который создает экземпляр актера Akka.NET в моем кластере как таковой:
_actorSystem = ActorSystem.Create("mycluster");
_actoraActor = this._actorSystem.ActorOf<ActorA>();
Обратите внимание, что я намеренно опускаю свойство name, поскольку намереваюсь создать N акторов типа ActorA и не хочу управлять именами. Запустив вышеизложенное, я получаю актера с идентификатором, который выглядит следующим образом:
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 @ локальный:666
Что имеет смысл, потому что это узел, который подключился к сети, а не актер.
Если я изменю свой код для использования именованного актера:
_actorSystem = ActorSystem.Create("mycluster");
_actoraActor = this._actorSystem.ActorOf<ActorA>("actora");
Затем я могу успешно запросить службу, как мне нужно. Это то, что вы ожидаете, когда у вас есть именованный актер, но, похоже, нет никакого способа фактически внешне определить экземпляры запущенных актеров на узле.
Итак, при использовании N экземпляров неназванных актеров, каковы правильные шаги для определения ссылок на актеров, которые вас интересуют, особенно когда актеры были сгенерированы без имени?
РЕДАКТИРОВАТЬ:
Я решил переформулировать вопрос, потому что изначально не описал его адекватно. Правильное выражение этого вопроса:
"Есть ли способ получить все экземпляры действующих экземпляров, доступные в данный момент на данном узле, от внешнего субъекта, когда у вас есть только путь к узлу?"
Мне просто кажется, что это должно быть что-то встроенное в базовую платформу, ЕСЛИ У меня есть некие конструктивные соображения, которые я не до конца понимаю.
Я также отмечаю, что, вероятно, правильный подход к моей конкретной проблеме может заключаться в том, что я пытаюсь создать Pub/Sub, и этот https://getakka.net/articles/clustering/distributed-publish-subscribe.html более подходящий.
1 ответ
Я думаю, что для ваших целей здесь вы должны рассмотреть возможность использования иерархии актеров.
Вместо создания актера верхнего уровня со случайно назначенным именем создайте родителя с жестко заданным именем:
_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);
});
}
}
Это дает вам фиксированную точку входа в этот узел / семейство актеров, в то же время имея возможность раскручивать новых актеров, у которых нет конкретных имен. Просто посмотрите на родителя со статическим именем, а не на детей, которые выполняют работу.
Пока вы занимаетесь этим, вам также может понадобиться взглянуть на маршрутизаторы пула и шаблон дочернего элемента в Akka.NET.