Akka.net 在隔离的节点上重启 actorsystem 终止

Akka.net restart actor system termination on node quarentined

我们正在开发一个带有 Akka.net v1.4.38 的集群,我们有使用 Akka.IO.TCP 与外部系统通信的种子节点,以及接收和发送消息到种子节点的多个客户端节点。如果客户端节点与集群失去通信,我们需要在该节点上重启 Akka actor 系统,因为它已被隔离。我们创建了一个侦听 AssociationErrorEvent 和 ThisActorSystemQuarantinedEvent 的 Actor,并在收到此消息时重新启动系统。

public class ErrorManagerActor: ReceiveActor {
    public ErrorManagerActor(Action action) {
        Receive<ThisActorSystemQuarantinedEvent>(m => {
            action();
        });
        Receive<AssociationErrorEvent>(m => {
            action();
        });
    }
}

问题是 actor 系统永远不会停止并在控制台中显示警告:

[CoordinatedShutdown (akka://xxxxx)] Coordinated shutdown phase [actor-system-terminate] timed out after 00:00:10

我们创建了一个单元测试来重现该问题。

    [Test]
    public void TerminateSystemTest() {
        var actor = Sys.ActorOf(Props.Create<ErrorManagerActor>(() => {
            if (!Sys.Terminate().Wait(10000))
                Assert.Fail("Unable to terminate actor system");
            terminatedEvent.Set();
        }));
        Sys.EventStream.Subscribe(actor, typeof(AssociationErrorEvent));
        Sys.EventStream.Subscribe(actor, typeof(ThisActorSystemQuarantinedEvent));
        var cluster = Cluster.Get(Sys);
        Sys.EventStream.Publish(new ThisActorSystemQuarantinedEvent(cluster.SelfAddress, cluster.SelfAddress));
        terminatedEvent.WaitOne();
    }

你的测试失败的原因是为了让 ActorSystem 终止它必须先杀死所有演员,包括 运行你的测试断言。因此让 actor 在 System.Terminate 上执行阻塞 Task.Wait 将导致死锁。

要在生产系统中修复此问题,不要等待 Task