Resilienz und Notfallwiederherstellung in Azure SignalR Service

Resilienz und Notfallwiederherstellung sind eine übliche Anforderung für Onlinesysteme. Azure SignalR Service bietet schon heute eine Verfügbarkeit von 99,9 %, ist aber noch immer ein regionaler Dienst. Wenn es einen regionsweiten Ausfall gibt, erfolgt für Ihre Dienstinstanz kein Failover zu einer anderen Region, da sie immer in der einen Region ausgeführt wird.

Für die regionale Notfallwiederherstellung empfehlen wir die folgenden beiden Ansätze:

  • Aktivieren der Georeplikation (einfache Methode): Mit diesem Feature wird das regionale Failover automatisch gehandhabt. Wenn es aktiviert ist, gibt es nur eine Azure SignalR-Instanz, und es werden keine Codeänderungen eingeführt. Weitere Informationen finden Sie unter Georeplikation.
  • Verwenden mehrerer Endpunkte im Dienst-SDK: Unser Dienst-SDK unterstützt mehrere SignalR-Dienstinstanzen und wechselt automatisch zu anderen Instanzen, wenn einige von ihnen nicht verfügbar sind. Mit diesem Feature können Sie bei einem Notfall eine Wiederherstellung durchführen, Sie müssen jedoch selbst die richtige Systemtopologie einrichten. In diesem Dokument erfahren Sie, wie Sie dazu vorgehen.

Hochverfügbare Architektur für SignalR Service

Um regionsübergreifende Resilienz für SignalR Service sicherzustellen, müssen Sie mehrere Dienstinstanzen in verschiedenen Regionen einrichten. So können beim Ausfall einer Region die anderen Regionen als Sicherung fungieren. Wenn App-Server mit mehreren Dienstinstanzen verbunden sind, gibt es zwei Rollen: die primäre und die sekundäre Instanz. Die primäre ist eine Instanz, die für den Empfang von Onlinedatenverkehr verantwortlich ist, während die sekundäre als Fallbackinstanz fungiert, die voll funktionsfähig ist. In unserer SDK-Implementierung werden bei der Aushandlung nur primäre Endpunkte zurückgegeben. Im Normalfall stellen Clients daher nur eine Verbindung mit primären Endpunkten her. Wenn die primäre Instanz ausfällt, werden bei der Aushandlung jedoch sekundäre Endpunkte zurückgegeben, damit Clients weiterhin eine Verbindung herstellen können. Die primäre Instanz und der App-Server werden über normale Serververbindungen verbunden. Die sekundäre Instanz und der App-Server aber werden über einen speziellen Verbindungstyp verbunden, der als „unsichere Verbindung“ bezeichnet wird. Ein Erkennungsmerkmal einer schwachen Verbindung besteht darin, dass das Clientverbindungsrouting aufgrund des Standorts der sekundären Instanz in einer anderen Region nicht akzeptiert werden kann. Das Routing eines Clients zu einer anderen Region ist keine optimale Lösung (die Latenz steigt).

Eine Dienstinstanz kann beim Herstellen einer Verbindung mit mehreren App-Servern unterschiedliche Rollen innehaben. Eine typische Konfiguration für ein regionsübergreifendes Szenario ist die Verwendung von zwei oder mehr Paaren von SignalR Service-Instanzen und App-Servern. Innerhalb jedes Paars befinden sich der App-Server und die SignalR Service-Instanz in derselben Region, und SignalR Service wird als primäre Rolle mit dem App-Server verbunden. Zwischen den einzelnen Paaren werden der App-Server und SignalR Service ebenfalls verbunden. SignalR wird beim Herstellen einer Verbindung mit einem Server in einer anderen Region jedoch zu einer sekundären Instanz.

In dieser Topologie können Nachrichten von einem Server weiterhin an alle Clients übermittelt werden, da alle App-Server und SignalR Service-Instanzen miteinander verbunden sind. Wenn ein Client eine Verbindung herstellt, wird er zum App-Server in der gleichen Region weitergeleitet, um eine optimale Netzwerklatenz zu erzielen.

Im folgenden Diagramm wird eine solche Topologie veranschaulicht.

Das Diagramm zeigt zwei Regionen, die jeweils einen App-Server und einen SignalR-Dienst aufweisen, und in denen jeder Server dem SignalR-Dienst für seine Region als primärer Server und dem Dienst in der anderen Region als sekundärer Server zugeordnet ist.

Konfigurieren von mehreren SignalR Service-Instanzen

Mehrere SignalR Service-Instanzen werden sowohl auf App-Servern als auch auf Azure-Funktionen unterstützt.

Nachdem Sie SignalR Service und App-Server/Azure Funktionen in jeder Region erstellt haben, können Sie Ihre App-Server/Azure-Funktionen zum Herstellen einer Verbindung mit allen SignalR Service-Instanzen konfigurieren.

Über die Konfigurationsdatei

Sie sollten bereits wissen, wie Sie die SignalR-Service-Verbindungszeichenfolge über Umgebungsvariablen/App-Einstellungen/web.config in einem Konfigurationseintrag namens Azure:SignalR:ConnectionString festlegen. Wenn Sie mehrere Endpunkte haben, können Sie diese in mehreren Konfigurationseinträgen im folgenden Format festlegen:

Azure:SignalR:ConnectionString:<name>:<role>

In ConnectionString ist <name> der Name des Endpunkts, und <role> ist die zugehörige Rolle (primär oder sekundär). Der Name ist optional. Er ist jedoch hilfreich, wenn Sie das Routingverhalten zwischen mehreren Endpunkten zusätzlich anpassen möchten.

Über den Code

Wenn Sie die Verbindungszeichenfolgen an anderer Stelle speichern möchten, können Sie sie auch in Ihrem Code einlesen und als Parameter beim Aufrufen von AddAzureSignalR() (ASP.NET Core) oder MapAzureSignalR() (ASP.NET) verwenden.

Sehen Sie sich den Beispielcode an:

ASP.NET Core:

services.AddSignalR()
        .AddAzureSignalR(options => options.Endpoints = new ServiceEndpoint[]
        {
            new ServiceEndpoint("<connection_string1>", EndpointType.Primary, "region1"),
            new ServiceEndpoint("<connection_string2>", EndpointType.Secondary, "region2"),
        });

ASP.NET:

app.MapAzureSignalR(GetType().FullName, hub,  options => options.Endpoints = new ServiceEndpoint[]
    {
        new ServiceEndpoint("<connection_string1>", EndpointType.Primary, "region1"),
        new ServiceEndpoint("<connection_string2>", EndpointType.Secondary, "region2"),
    };

Sie können mehrere primäre oder sekundäre Instanzen konfigurieren. Wenn mehrere primäre und/oder sekundäre Instanzen vorhanden sind, gibt das Aushandeln einen Endpunkt in dieser Reihenfolge zurück:

  1. Wenn mindestens eine primäre Instanz online ist, wird eine zufällige primäre Onlineinstanz zurückgegeben.
  2. Wenn alle primären Instanzen ausgefallen sind, wird eine zufällige sekundäre Onlineinstanz zurückgegeben.

Für Azure Functions SignalR-Bindungen

Um mehrere SignalR Service-Instanzen zu aktivieren:

  1. Verwenden Sie den Transporttyp Persistent.

    Der Standardtransporttyp ist der Transient-Modus. Fügen Sie Ihrer local.settings.json-Datei oder der Anwendungseinstellung in Azure den folgenden Eintrag hinzu.

    {
        "AzureSignalRServiceTransportType":"Persistent"
    }
    

    Hinweis

    Wenn Sie vom Transient-Modus in den Persistent-Modus wechseln, kann sich das JSON-Serialisierungsverhalten ändern, da im Transient-Modus die Newtonsoft.Json-Bibliothek verwendet wird, um Argumente von Hubmethoden zu serialisieren, die System.Text.Json-Bibliothek wird jedoch im Persistent-Modus als Standard verwendet. System.Text.Json weist einige wichtige Unterschiede beim Standardverhalten im Vergleich zu Newtonsoft.Json auf. Wenn Sie Newtonsoft.Json im Persistent-Modus verwenden möchten, können Sie ein Konfigurationselement hinzufügen: "Azure:SignalR:HubProtocol":"NewtonsoftJson" in der local.settings.json-Datei oder Azure__SignalR__HubProtocol=NewtonsoftJson im Azure-Portal.

  2. Konfigurieren Sie mehrere SignalR Service-Endpunkteinträge in Ihrer Konfiguration.

    Wir verwenden ein ServiceEndpoint-Objekt, um eine SignalR Service-Instanz zu repräsentieren. Sie können einen Dienstendpunkt mit <EndpointName> und <EndpointType> im Eintragsschlüssel und der Verbindungszeichenfolge im Eintragswert definieren. Die Schlüssel befinden sich im folgenden Format:

    Azure:SignalR:Endpoints:<EndpointName>:<EndpointType>
    

    <EndpointType> ist optional und standardmäßig auf primary festgelegt. Beispiele finden Sie hier:

    {
        "Azure:SignalR:Endpoints:EastUs":"<ConnectionString>",
    
        "Azure:SignalR:Endpoints:EastUs2:Secondary":"<ConnectionString>",
    
        "Azure:SignalR:Endpoints:WestUs:Primary":"<ConnectionString>"
    }
    

    Hinweis

    • Wenn Sie Azure SignalR-Endpunkte in App Service im Azure-Portal konfigurieren, vergessen Sie nicht, ":" durch "__" zu ersetzen, den doppelten Unterstrich in den Schlüsseln. Die Begründung finden Sie unter Umgebungsvariablen.

    • Die mit dem Schlüssel {ConnectionStringSetting} konfigurierte Verbindungszeichenfolge (Standardeinstellung „AzureSignalRConnectionString“) wird auch als primärer Dienstendpunkt mit leerem Namen erkannt. Dieser Konfigurationsstil wird jedoch für mehrere Endpunkte nicht empfohlen.

Für das Management SDK

Hinzufügen mehrerer Endpunkte über die Konfiguration

Verwenden Sie für die Konfiguration den Schlüssel Azure:SignalR:Endpoints als SignalR Service-Verbindungszeichenfolge. Der Schlüssel sollte das Format Azure:SignalR:Endpoints:{Name}:{EndpointType} aufweisen. Hierbei sind Name und EndpointType Eigenschaften des ServiceEndpoint-Objekts, die über den Code zugänglich sind.

Sie können Verbindungszeichenfolgen für mehrere Instanzen hinzufügen, indem Sie die folgenden dotnet-Befehle verwenden:

dotnet user-secrets set Azure:SignalR:Endpoints:east-region-a <ConnectionString1>
dotnet user-secrets set Azure:SignalR:Endpoints:east-region-b:primary <ConnectionString2>
dotnet user-secrets set Azure:SignalR:Endpoints:backup:secondary <ConnectionString3>

Hinzufügen mehrerer Endpunkte über Code

Eine ServiceEndpoint-Klasse beschreibt die Eigenschaften eines Azure SignalR Service-Endpunkts. Sie können mehrere Instanzen für Endpunkte konfigurieren, wenn Sie das Azure SignalR Management SDK verwenden:

var serviceManager = new ServiceManagerBuilder()
                    .WithOptions(option =>
                    {
                        options.Endpoints = new ServiceEndpoint[]
                        {
                            // Note: this is just a demonstration of how to set options.Endpoints
                            // Having ConnectionStrings explicitly set inside the code is not encouraged
                            // You can fetch it from a safe place such as Azure KeyVault
                            new ServiceEndpoint("<ConnectionString0>"),
                            new ServiceEndpoint("<ConnectionString1>", type: EndpointType.Primary, name: "east-region-a"),
                            new ServiceEndpoint("<ConnectionString2>", type: EndpointType.Primary, name: "east-region-b"),
                            new ServiceEndpoint("<ConnectionString3>", type: EndpointType.Secondary, name: "backup"),
                        };
                    })
                    .BuildServiceManager();

Failoversequenz und bewährte Methode

Sie verfügen jetzt über die richtige Konfiguration der Systemtopologie. Sollte eine SignalR Service-Instanz ausfallen, wird Onlinedatenverkehr zu anderen Instanzen geleitet. Folgendes geschieht, wenn eine primäre Instanz ausfällt (und später wiederhergestellt wird):

  1. Die primäre Dienstinstanz ist ausgefallen, und alle Serververbindungen für diese Instanz werden getrennt.
  2. Alle Server, die mit dieser Instanz verbunden sind, markieren die Instanz als „offline“. Bei der Aushandlung wird nicht mehr dieser Endpunkt zurückgegeben, sondern der sekundäre Endpunkt.
  3. Alle Clientverbindungen auf dieser Instanz werden ebenfalls geschlossen. Clients stellen dann eine neue Verbindung her. Da App-Server jetzt den sekundären Endpunkt zurückgeben, stellen Clients eine Verbindung mit der sekundären Instanz her.
  4. Die sekundäre Instanz übernimmt nun den gesamten Onlinedatenverkehr. Alle Nachrichten vom Server an Clients können weiterhin übermittelt werden, da die sekundäre Instanz mit allen App-Servern verbunden ist. Nachrichten von Clients an Server werden jedoch nur an den App-Server in der gleichen Region weitergeleitet.
  5. Nachdem die primäre Instanz wiederhergestellt wurde und wieder online ist, stellt der App-Server die Verbindungen wieder her und markiert die Instanz als „online“. Bei der Aushandlung wird jetzt wieder der primäre Endpunkt zurückgegeben, sodass neue Clients mit dem primären Endpunkt verbunden werden. Vorhandene Clients werden jedoch nicht getrennt, sondern weiterhin an die sekundäre Instanz weitergeleitet, bis sie sich selbst trennen.

Die folgenden Diagramme veranschaulichen das Failover in SignalR Service:

Abb. 1 Vor dem Failover Vor dem Failover

Abb. 2 Nach dem Failover Nach dem Failover

Abb. 3 Kurze Zeit nach der Wiederherstellung der primären Instanz Kurze Zeit nach der Wiederherstellung der primären Instanz

Wie Sie sehen, liegt im Normalfall nur für den primären App-Server und die primäre SignalR Service-Instanz Onlinedatenverkehr vor (blau dargestellt). Nach dem Failover werden auch der sekundäre App-Server und die sekundäre SignalR Service-Instanz aktiv. Wenn die primäre SignalR Service-Instanz wieder online ist, stellen neue Clients eine Verbindung mit der primären SignalR-Instanz her. Vorhandene Clients stellen jedoch weiterhin eine Verbindung mit der sekundären Instanz her, sodass beide Instanzen Datenverkehr verarbeiten. Nachdem alle vorhandenen Clients die Verbindung getrennt haben, kehrt das System zum normalen Betriebszustand zurück (Abb. 1).

Für die Implementierung einer regionsübergreifenden hochverfügbaren Architektur stehen zwei grundlegende Muster zur Verfügung:

  1. Verwendung eines Paars von App-Server und SignalR Service-Instanz, das den gesamten Onlinedatenverkehr verarbeitet, und eines weiteren Paars als Sicherung (bezeichnet als Aktiv/Passiv-Konfiguration, siehe Abb. 1).
  2. Verwendung von zwei (oder mehr) Paaren von App-Servern und Azure SignalR Service-Instanzen, die alle Onlinedatenverkehr verarbeiten und als Sicherung für andere Paare fungieren (bezeichnet als Aktiv/Aktiv-Konfiguration, siehe Abb. 3).

SignalR Service kann beide Muster unterstützen. Der wesentliche Unterschied besteht in der Implementierung der App-Server. Wenn App-Server aktiv/passiv sind, sind auch die SignalR Service-Instanzen aktiv/passiv (weil der primäre App-Server nur seine primäre SignalR Service-Instanz zurückgibt). Wenn App-Server aktiv/aktiv sind, sind auch die SignalR Service-Instanzen aktiv/aktiv (weil alle App-Server ihre eigenen primären SignalR-Instanzen zurückgeben und daher alle Datenverkehr empfangen können).

Beachten Sie, dass Sie unabhängig vom ausgewählten Muster jede SignalR Service-Instanz als primäre Instanz mit einem App-Server verbinden müssen.

Da die SignalR-Verbindung eine lange Verbindung ist, treten zudem im Fall eines Notfalls und Failovers Verbindungsabbrüche bei Clients auf. Sie müssen solche Verbindungsabbrüche auf der Clientseite behandeln, damit sie für Ihre Endkunden transparent sind. Stellen Sie beispielsweise nach dem Schließen einer Verbindung erneut eine Verbindung her.

Testen eines Failovers

Führen Sie die Schritte aus, um das Failover auszulösen:

  1. Deaktivieren Sie auf der Registerkarte „Netzwerk“ den öffentlichen Netzwerkzugriff für die primäre Ressource im Portal. Wenn für die Ressource ein privates Netzwerk aktiviert ist, verwenden Sie Zugriffssteuerungsregeln, um den gesamten Datenverkehr zu verweigern.
  2. Starten Sie die primäre Ressource neu.

Nächste Schritte

In diesem Artikel haben Sie gelernt, wie Sie Ihre Anwendung konfigurieren, um Resilienz für SignalR Service zu erzielen. Weitere Details zur Server-/Clientverbindung und zum Verbindungsrouting in SignalR Service finden Sie in diesem Artikel.

Informationen zu Skalierungsszenarios wie z. B. Sharding, bei denen mehrere Instanzen zusammen verwendet werden, um eine große Anzahl von Verbindungen zu handhaben, finden Sie unter Skalieren mehrerer Instanzen.

Ausführliche Informationen zum Konfigurieren von Azure Functions mit mehreren SignalR Service-Instanzen finden Sie unter Unterstützung mehrerer Azure SignalR Service-Instanzen in Azure-Funktionen.