Ordnungsgemäßes Herunterfahren von Servern

Microsoft Azure SignalR Service bietet zwei Modi zum ordnungsgemäßen Herunterfahren eines SignalR-Hubservers, wenn Azure SignalR Service als Standardmodus konfiguriert ist, Azure SignalR Service als Proxy zwischen den SignalR-Clients und dem SignalR-Hubserver fungiert.

Der Hauptvorteil der Verwendung dieses Features besteht darin, dass bei Ihrem Kunden keine unerwarteten Verbindungsausfälle auftreten.

Stattdessen können Sie in Ihrer Geschäftslogik darauf warten, dass Ihre Clientverbindungen selbstständig getrennt werden, oder Sie können die Clientverbindung sogar zu einem anderen Server migrieren, ohne Daten zu verlieren.

Funktionsweise

Im Allgemeinen erfolgt das ordnungsgemäße Herunterfahren in vier Phasen:

  1. Versetzen des Servers in den Offlinemodus

    Dadurch werden keine weiteren Clientverbindungen an diesen Server weitergeleitet.

  2. Auslösen von OnShutdown-Hooks

    Sie können für jeden Hub in Ihrem Besitz auf dem Server Shutdown-Hooks registrieren. Sie werden in Bezug auf den registrierten Auftrag aufgerufen, nachdem wir eine FINACK-Antwort von unserem Azure SignalR-Dienst erhalten haben, was bedeutet, dass dieser Server offline im Azure SignalR-Dienst festgelegt wurde.

    Sie können Nachrichten übertragen oder einige sauber Ing-Aufträge in dieser Phase ausführen, sobald alle Herunterfahren-Hooks ausgeführt wurden, werden wir mit der nächsten Phase fortfahren.

  3. Warten auf das Trennen aller Clientverbindungen. Dies ist vom ausgewählten Modus abhängig, der einer der folgenden sein kann:

    Modus WaitForClientsToClose

    Azure SignalR Service wartet auf vorhandene Clients.

    Möglicherweise müssen Sie eine Möglichkeit entwerfen, z. B. eine Abschlussnachricht an alle Clients übertragen, und lassen Sie Ihre Clients entscheiden, wann sie sich selbst schließen/erneut verbinden möchten.

    Sehen Sie sich das ChatSample an. Dort finden Sie ein Beispiel, bei dem über einen Shutdown-Hook eine „exit“-Meldung übertragen wird, um die Clients zu trennen.

    Modus MigrateClients

    Azure SignalR Service versucht, die Clientverbindungen auf diesem Server auf einen anderen gültigen Server umzuleiten.

    In diesem Szenario und wird auf dem neuen Server bzw. dem alten Server mit einem IConnectionMigrationFeature Satz im ContextBereich ausgelöst, der verwendet werden kann, um zu ermitteln, OnConnectedAsyncOnDisconnectedAsync ob die Clientverbindung migriert oder migriert wurde. Dieses Feature kann besonders für zustandsbehaftete Szenarien nützlich sein.

    Die Clientverbindung wird sofort migriert, nachdem die aktuelle Nachricht übermittelt wurde. Dies bedeutet, dass die nächste Nachricht an den neuen Server weitergeleitet wird.

  4. Trennen der Serververbindungen

    Nachdem alle Clientverbindungen getrennt/migriert wurden oder das Timeout (standardmäßig 30 s) überschritten wurde, geschieht Folgendes:

    Das SignalR-Server SDK fährt mit dieser Phase des Herunterfahrens fort und schließt alle Serververbindungen.

    Clientverbindungen, die nicht geschlossen oder migriert wurden, werden trotzdem getrennt. Beispiele sind das Fehlen eines geeigneten Zielservers oder eine nicht abgeschlossene Meldung vom aktuellen Client zum Server.

Codebeispiele

Fügen Sie bei Verwendung von AddAzureSignalR folgende Optionen hinzu:

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

Konfigurieren von OnConnected und OnDisconnected beim Herunterfahrmodus MigrateClients

Wir haben ein "I Verbinden ionMigrationFeature" eingeführt, um anzugeben, ob eine Verbindung migriert/out wurde.

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