簡體   English   中英

Akka.NET集群節點正常關閉

[英]Akka.NET cluster node graceful shutdown

背景

我有一個包含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();
    }
}

這是我的主要內容:

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));
        });
    }
}

當單步執行Stop功能時,我看不到任何有關節點離開其他節點的消息。 但是,當函數返回時,其他節點開始噴出異常。

Akka.NET Gitter頻道的用戶說:

即使沒有TopShelf我也必須說,在webhost終止后使用純ASP.NET核心項目,我觀察到同樣的事情。

我可以添加什么讓其他節點收到有關節點離開的消息?

我認為問題是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();
    }

}

注意:我檢查了三種類型的應用程序如何離開群集沒有問題。 我在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();
    }

}

這更簡單,可以處理更復雜的清理方案,例如在終止集群本身之前關閉Akka.Cluster.Sharding。 我相信這是自Akka.NET 1.3.2以來推薦的做事方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM