Перечисление доступных актеров в кластере Akka.NET
У меня есть два актера, давайте назовем их ActorA и ActorB. Оба участника находятся в своем собственном отдельном процессе в качестве службы Windows на основе Topshelf.
В основном они выглядят так.
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;
}
}
Мои конфигурационные файлы очень просты
ActorA:
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]
}
}
ActorB:
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
сообщение. Однако я могу успешно отправить любой другой тип сообщения ActorA, используя ту же ссылку ActorSelection.
Так может ли кто-нибудь предоставить какое-либо понимание? Почему мое удостоверение личности никогда не достигает моего целевого актера?
1 ответ
Сообщение ActorIdentity вызывается в ActorB, а не в ActorA.
Это работает как задумано, так как вы отправляете Identify
запрос от актера B → A, для которого ActorIdentity
ответное сообщение (отправляется автоматически от A → B).
Вы уже можете наблюдать это поведение в действии, так как:
Context.ActorSelection(path).ResolveOne(timeout)
является более или менее эквивалентом
Context.ActorSelection(path).Ask<ActorIdentity>(new Identify(null), timeout: timeout)
Identify
является системным сообщением, которое обрабатывается всегда до вызова любых определенных программистом обработчиков сообщений - по этой причине вы, вероятно, не поймаете его в своих собственных обработчиках.