Грамотное завершение узла кластера Akka.NET

Фон

У меня есть кластер Akka.NET, содержащий начальный узел Lighthouse и два других узла, использующих системы акторов. Когда я пытаюсь сделать постепенное завершение работы на одном из узлов кластера, я хочу видеть, что по крайней мере один из других узлов видит сообщение об уходе узла и что все узлы кластера в конечном итоге исключают уходящий узел из списка узлов.

После того, как об этом позаботятся, я ожидаю, что смогу отключить узел без двух других узлов, сходящих с ума из-за невозможности подключения к узлу, который выключился.

Что я пробовал

Сейчас у меня есть консольное приложение, обернутое в приложение 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, я должен сказать, с чистым проектом ASP.NET Core после прекращения работы веб-хостинга.

Вопрос

Что можно добавить, чтобы другие узлы получали сообщение об уходе узла?

2 ответа

Решение

Я думаю, что проблема в том, что Stop() Метод завершается до завершения ухода. Вам следует дождаться события MemberRemoved.

это Stop() Метод будет ждать, пока не будет вызван обратный вызов MemberRemoved и сообщен о том, что он даже завершил систему субъекта.

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.

Другие вопросы по тегам