max*_*paj 16 c# akka.net akka.net-cluster
我有一个包含Lighthouse种子节点的Akka.NET集群和另外两个运行actor系统的节点.当我尝试在我的一个群集节点上正常关闭时,我想看到至少有一个其他节点看到有关该节点离开的消息,并且所有群集节点最终都排除了节点列表的离开节点.
一旦完成了这一点,我希望我能够关闭节点,而其他两个节点不会因为无法连接到关闭的节点而疯狂.
我现在拥有的是一个包含在TopShelf应用程序中的控制台应用程序:
class ActorService : ServiceControl
{
private ActorSystem _actorSystem;
public bool Start(HostControl hostControl)
{
_actorSystem = ActorSystem.Create("myActorSystem");
var cluster = Cluster.Get(_actorSystem);
cluster.RegisterOnMemberRemoved(_Terminate);
return true;
}
public bool Stop(HostControl hostControl)
{
var cluster = Cluster.Get(_actorSystem);
cluster.Leave(cluster.SelfAddress);
return true;
}
private void _Terminate()
{
_actorSystem.Terminate();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的主要内容:
class Program
{
static int Main(string[] args)
{
return (int) HostFactory.Run(x =>
{
x.UseAssemblyInfoForServiceInfo();
x.RunAsLocalSystem();
x.StartAutomatically();
x.Service<ActorService>();
x.EnableServiceRecovery(r => r.RestartService(1));
});
}
}
Run Code Online (Sandbox Code Playgroud)
当单步执行Stop功能时,我看不到任何有关节点离开其他节点的消息.但是,当函数返回时,其他节点开始喷出异常.
Akka.NET Gitter频道的用户说:
即使没有TopShelf我也必须说,在webhost终止后使用纯ASP.NET核心项目,我观察到同样的事情.
我可以添加什么让其他节点收到有关节点离开的消息?
Zoo*_*Way 19
我认为问题是该Stop()方法在离开完成之前完成.您应该等待MemberRemoved事件.
此Stop()方法将一直等到调用MemberRemoved回调并发出信号表明它甚至已终止了actor系统.
class Worker
{
private static readonly ManualResetEvent asTerminatedEvent = new ManualResetEvent(false);
private ActorSystem actorSystem;
public void Start()
{
this.actorSystem = ActorSystem.Create("sample");
}
public void Stop()
{
var cluster = Akka.Cluster.Cluster.Get(actorSystem);
cluster.RegisterOnMemberRemoved(() => MemberRemoved(actorSystem));
cluster.Leave(cluster.SelfAddress);
asTerminatedEvent.WaitOne();
//log.Info("Actor system terminated, exiting");
}
private async void MemberRemoved(ActorSystem actorSystem)
{
await actorSystem.Terminate();
asTerminatedEvent.Set();
}
}
Run Code Online (Sandbox Code Playgroud)
注意:我检查了三种类型的应用程序如何离开群集没有问题.我在GitHub上托管了它.离开时仍有一些例外和一些死信,但其他节点不再继续尝试重新连接到退出的节点.
我想在这个帖子上发布一个更新,因为我们已经为Akka.NET添加了一个新功能,因为这个答案最初是被接受的: CoordinatedShutdown
它完成了@ ZoolWay的回答以及更多内容,但要使用它,您只需要做以下事情:
class Worker
{
private ActorSystem actorSystem;
public void Start()
{
this.actorSystem = ActorSystem.Create("sample");
}
public void Stop()
{
Task<Done> shutdownTask = CoordinatedShutdown.Get(actorSystem).Run(CoordinatedShutdown.ClrExitReason.Instance);
shutdownTask.Wait();
}
}
Run Code Online (Sandbox Code Playgroud)
这更简单,可以处理更复杂的清理方案,例如在终止集群本身之前关闭Akka.Cluster.Sharding.我相信这是自Akka.NET 1.3.2以来推荐的做事方式.