Udostępnij za pośrednictwem


Bezproblemowe zamykanie serwera

Usługa Microsoft Azure SignalR Service udostępnia dwa tryby bezpiecznego zamykania serwera usługi SignalR Hub, gdy usługa Azure SignalR Service jest skonfigurowana jako tryb domyślny, który usługa Azure SignalR Service działa jako serwer proxy między klientami SignalR i serwerem usługi SignalR Hub.

Kluczową zaletą korzystania z tej funkcji jest uniemożliwienie klientowi nieoczekiwanego przerywania połączenia.

Zamiast tego można zaczekać na zamknięcie połączeń klienta w odniesieniu do logiki biznesowej, a nawet zmigrować połączenie klienta z innym serwerem bez utraty danych.

Jak to działa

Ogólnie rzecz biorąc, w procesie bezpiecznego zamykania będą istnieć cztery etapy:

  1. Ustawianie serwera w trybie offline

    Oznacza to, że żadne połączenia klienta nie będą kierowane do tego serwera.

  2. Wyzwalacze OnShutdown zaczepienia

    Można zarejestrować haki zamknięcia dla każdego koncentratora, którego jesteś właścicielem na serwerze. Będą one wywoływane w odniesieniu do zarejestrowanego zamówienia bezpośrednio po utworzeniu odpowiedzi FINACK z usługi Azure SignalR Service, co oznacza, że ten serwer został ustawiony w trybie offline w usłudze Azure SignalR Service.

    Komunikaty można rozgłaszać lub wykonywać niektóre zadania czyszczenia na tym etapie, gdy wszystkie haki zamknięcia zostały wykonane, przejdziemy do następnego etapu.

  3. Poczekaj na zakończenie wszystkich połączeń klienckich, zależy od wybranego trybu, może to być:

    Tryb ustawiony na WaitForClientsToClose

    Usługa Azure SignalR Service będzie przechowywać istniejących klientów.

    Może być konieczne zaprojektowanie sposobu, takiego jak emisja komunikatu zamykającego do wszystkich klientów, a następnie pozwolić klientom zdecydować, kiedy zamknąć/ponownie nawiązać połączenie.

    Przeczytaj plik ChatSample na potrzeby przykładowego użycia, który emitujemy komunikat "exit", aby wyzwolić zamknięcie klienta w haczyku zamykania.

    Tryb ustawiony na MigrateClients

    Usługa Azure SignalR Service spróbuje przekierować połączenie klienta na tym serwerze z innym prawidłowym serwerem.

    W tym scenariuszu OnConnectedAsync i OnDisconnectedAsync zostanie wyzwolony na nowym serwerze i starym serwerze odpowiednio z zestawem IConnectionMigrationFeature w Contextsystemie , który może służyć do określenia, czy połączenie klienta zostało zmigrowane lub zmigrowane. Ta funkcja może być przydatna szczególnie w przypadku scenariuszy stanowych.

    Połączenie klienta zostanie natychmiast zmigrowane po dostarczeniu bieżącego komunikatu, co oznacza, że następny komunikat zostanie przekierowany do nowego serwera.

  4. Zatrzymywanie połączeń serwera

    Po zamknięciu/zmigrowania wszystkich połączeń klienckich lub przekroczeniu limitu czasu (domyślnie 30s)

    Zestaw SDK serwera SignalR przeprowadzi proces zamykania do tego etapu i zamknie wszystkie połączenia serwera.

    Połączenia klienckie będą nadal przerywane, jeśli nie można go zamknąć/zmigrować. Na przykład nie został ukończony żaden odpowiedni serwer docelowy/bieżący komunikat klient-serwer.

Przykładowe kody.

Dodaj następujące opcje, gdy AddAzureSignalR:

services.AddSignalR().AddAzureSignalR(option =>
{
    option.GracefulShutdown.Mode = GracefulShutdownMode.WaitForClientsClose;
    // option.GracefulShutdown.Mode = GracefulShutdownMode.MigrateClients;
    option.GracefulShutdown.Timeout = TimeSpan.FromSeconds(30);

    option.GracefulShutdown.Add<Chat>(async (c) =>
    {
        await c.Clients.All.SendAsync("exit");
    });
});

skonfiguruj OnConnected i OnDisconnected podczas ustawiania bezpiecznego trybu zamykania na MigrateClientswartość .

Wprowadziliśmy element "I Połączenie ionMigrationFeature", aby wskazać, czy połączenie było migrowane/wychodzące.

public class Chat : Hub {

    public override async Task OnConnectedAsync()
    {
        Console.WriteLine($"{Context.ConnectionId} connected.");

        var feature = Context.Features.Get<IConnectionMigrationFeature>();
        if (feature != null)
        {
            Console.WriteLine($"[{feature.MigrateTo}] {Context.ConnectionId} is migrated from {feature.MigrateFrom}.");
            // Your business logic.
        }

        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception e)
    {
        Console.WriteLine($"{Context.ConnectionId} disconnected.");

        var feature = Context.Features.Get<IConnectionMigrationFeature>();
        if (feature != null)
        {
            Console.WriteLine($"[{feature.MigrateFrom}] {Context.ConnectionId} will be migrated to {feature.MigrateTo}.");
            // Your business logic.
        }

        await base.OnDisconnectedAsync(e);
    }
}