Condividi tramite


Resilienza e ripristino di emergenza nel Servizio Azure SignalR

La resilienza e il ripristino di emergenza sono un'esigenza comune per i sistemi online. Il servizio Azure SignalR offre già una disponibilità del 99,9%, ma è ancora un servizio a livello di area. Quando si verifica un'interruzione a livello di area, l'istanza del servizio non esegue il failover in un'altra area perché è sempre in esecuzione in un'unica area.

Per il ripristino di emergenza a livello di area, è consigliabile adottare i due approcci seguenti:

  • Abilitare la replica geografica (modo semplice). Questa funzionalità gestisce automaticamente il failover a livello di area. Se abilitata, è presente una sola istanza di Azure SignalR e non vengono introdotte modifiche al codice. Controllare la replica geografica per informazioni dettagliate.
  • Usare più endpoint nell'SDK del servizio. L'SDK del servizio supporta più istanze del servizio SignalR e passa automaticamente ad altre istanze quando alcune di esse non sono disponibili. Con questa funzionalità si può eseguire il ripristino in caso di emergenza, ma è necessario configurare autonomamente la topologia di sistema appropriata. Questo documento illustra come procedere.

Architettura a disponibilità elevata per il servizio SignalR

Per garantire resilienza tra aree per il servizio SignalR, è necessario configurare più istanze del servizio in aree diverse. In questo modo, quando un'area è inattiva è possibile usare le altre come backup. Quando i server app si connettono a più istanze del servizio, esistono due ruoli: primario e secondario. Quella primaria è un'istanza responsabile della ricezione del traffico online, mentre la secondaria funge da istanza di fallback completamente funzionante. Nell'implementazione dell'SDK, la negoziazione restituisce solo gli endpoint primari, quindi normalmente i client si connettono solo agli endpoint primari. Quando l'istanza primaria è inattiva, tuttavia, la negoziazione restituisce gli endpoint secondari affinché il client possa comunque connettersi. L'istanza primaria e il server app sono connessi tramite una connessione al server normale, mentre l'istanza secondaria e il server app sono connessi tramite una speciale tipologia di connessione denominata connessione debole. Una caratteristica distintiva di una connessione debole è che non è in grado di accettare il routing della connessione client a causa della posizione dell'istanza secondaria in un'altra area. Il routing di un client a un'altra area non è una soluzione ottimale, perché aumenta la latenza.

Un'istanza del servizio può avere diversi ruoli se connessa a più server app. Una configurazione tipica per uno scenario che include più aree consiste nell'avere due o più coppie di server app e istanze del servizio SignalR. All'interno di ogni coppia, il server app e il servizio SignalR si trovano nella stessa area e il servizio SignalR è connesso al server app come ruolo primario. Server app e servizio SignalR sono connessi anche tra le coppie, ma SignalR diventa un ruolo secondario nella connessione al server di un'altra area.

Con questa topologia, un messaggio da un server può comunque essere recapitato a tutti i client perché tutti i server app e le istanze del servizio SignalR sono interconnessi. Al momento della connessione, tuttavia, un client viene indirizzato al server app nella stessa area per ottenere una latenza di rete ottimale.

Il diagramma seguente illustra tale topologia:

Il diagramma mostra due aree, ognuna con un server app e un servizio SignalR, in cui ogni server è associato al servizio SignalR nella propria area come primario e con il servizio nell'altra area come secondario.

Configurare più istanze del servizio SignalR

Sono supportate più istanze del servizio SignalR sia nei server app che in Funzioni di Azure.

Dopo aver creato il servizio SignalR e i server app/Funzioni di Azure in ogni area, è possibile configurare i server app/Funzioni di Azure per la connessione a tutte le istanze del servizio SignalR.

Tramite configurazione

Dovrebbe essere già noto come impostare la stringa di connessione del servizio SignalR tramite variabili di ambiente/impostazioni dell'app/web.config, con una voce di configurazione denominata Azure:SignalR:ConnectionString. Se sono presenti più endpoint, si possono impostare in più voci di configurazione, ognuna con il formato seguente:

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

In ConnectionString, <name> è il nome dell'endpoint e <role> è il relativo ruolo (primario o secondario). Il nome è facoltativo, ma è utile se si vuole personalizzare ulteriormente il comportamento di routing tra più endpoint.

Tramite codice

Se si preferisce archiviare le stringhe di connessione in un'altra posizione, è possibile eseguirne la lettura nel codice e usarle come parametro durante la chiamata di AddAzureSignalR() (in ASP.NET Core) o MapAzureSignalR() (in ASP.NET).

Ecco il codice di esempio:

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

È possibile configurare più istanze primarie o secondarie. Se sono presenti più istanze primarie e/o secondarie, negotiate restituisce un endpoint nell'ordine seguente:

  1. Se è online almeno un'istanza primaria, restituisce un'istanza primaria casuale online.
  2. Se tutte le istanze primarie sono inattive, restituire un'istanza online secondaria casuale.

Per le associazioni SignalR per Funzioni di Azure

Per abilitare più istanze del servizio SignalR, è necessario:

  1. Usare il tipo di trasporto Persistent.

    Il tipo di trasporto predefinito è la modalità Transient. È necessario aggiungere la voce seguente al file local.settings.json o all'impostazione dell'applicazione in Azure.

    {
        "AzureSignalRServiceTransportType":"Persistent"
    }
    

    Nota

    Quando si passa dalla modalità Transient alla modalità Persistent, potrebbe verificarsi una modifica del comportamento di serializzazione JSON, perché in modalità Transient viene usata la libreria Newtonsoft.Json per serializzare gli argomenti dei metodi hub, tuttavia, in modalità Persistent, la libreria System.Text.Json viene usata come predefinita. System.Text.Json presenta alcune differenze principali nel comportamento predefinito con Newtonsoft.Json. Se si vuole usare Newtonsoft.Json in modalità Persistent, è possibile aggiungere un elemento di configurazione: "Azure:SignalR:HubProtocol":"NewtonsoftJson" nel file local.settings.json o Azure__SignalR__HubProtocol=NewtonsoftJson nel portale di Azure.

  2. Configurare più voci degli endpoint del servizio SignalR nella configurazione.

    Viene usato un oggetto ServiceEndpoint per rappresentare un'istanza del servizio SignalR. È possibile definire un endpoint di servizio con il relativo <EndpointName> e <EndpointType> nella chiave di immissione e la stringa di connessione nel valore della voce. Le chiavi sono nel formato seguente:

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

    <EndpointType> è facoltativo e il valore predefinito è primary. Vedere gli esempi seguenti:

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

    Nota

    • Quando si configurano gli endpoint di Azure SignalR nel servizio app nel portale di Azure, non dimenticare di sostituire ":" con "__", il doppio carattere di sottolineatura nelle chiavi. Per sapere perché, vedere Variabili di ambiente.

    • La stringa di connessione configurata con la chiave {ConnectionStringSetting} (l'impostazione predefinita è "AzureSignalRConnectionString") viene riconosciuta anche come endpoint di servizio primario con nome vuoto. Questo stile di configurazione non è tuttavia consigliato per più endpoint.

Per SDK Management

Aggiungere più endpoint dalla configurazione

Configurare con la chiave Azure:SignalR:Endpoints per la stringa di connessione del servizio SignalR. La chiave deve essere nel formato Azure:SignalR:Endpoints:{Name}:{EndpointType}, dove Name e EndpointType sono proprietà dell'oggetto ServiceEndpoint e sono accessibili dal codice.

È possibile aggiungere più stringhe di connessione dell'istanza usando i comandi dotnet seguenti:

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>

Aggiungere più endpoint dal codice

Una classe ServiceEndpoint descrive le proprietà di un endpoint del servizio Azure SignalR. È possibile configurare più endpoint di istanza quando si usa Azure SignalR Management SDK tramite:

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

Sequenza di failover e procedure consigliate

La configurazione della topologia di sistema è ora appropriata. Ogni volta che un'istanza del servizio SignalR è inattiva, il traffico online viene indirizzato alle altre istanze. Quando un'istanza primaria è inattiva e viene ripristinata in un secondo momento, si verifica quanto segue:

  1. L'istanza primaria del servizio è inattiva e tutte le connessioni al server di tale istanza vengono interrotte.
  2. Tutti i server connessi all'istanza la contrassegnano come offline. La negoziazione non restituisce più questo endpoint e inizia a restituire l'endpoint secondario.
  3. Vengono chiuse anche tutte le connessioni client dell'istanza e i client si riconnettono. Dato che i server app restituiscono l'endpoint secondario, i client si connettono all'istanza secondaria.
  4. L'istanza secondaria gestisce ora tutto il traffico online. Tutti i messaggi dal server ai client possono comunque essere recapitati perché l'istanza secondaria è connessa a tutti i server app. I messaggi dai client al server, tuttavia, vengono indirizzati solo al server app nella stessa area.
  5. Quando l'istanza primaria è ripristinata e di nuovo online, il server app ristabilisce le connessioni all'istanza e la contrassegna come online. La negoziazione restituisce di nuovo l'endpoint primario, quindi i nuovi client vengono connessi all'istanza primaria. Ma i client esistenti non vengono interrotti e vengono comunque indirizzati all'istanza secondaria fino a quando non si disconnettono.

I diagrammi seguenti illustrano come viene effettuato il failover nel servizio SignalR:

Fig.1 Prima del failover Prima del failover

Fig.2 Dopo il failover Dopo il failover

Fig.3 Breve tempo dopo il ripristino dell'istanza primaria Breve tempo dopo il ripristino dell'istanza primaria

Come si può osservare, normalmente il traffico online (in blu) viene gestito solo dal server app e dal servizio SignalR primari. Dopo il failover, diventano attivi anche il server app e il servizio SignalR secondari. Quando il servizio SignalR primario è di nuovo online, i nuovi client si connetteranno al servizio SignalR primario. I client esistenti restano invece connessi a quello secondario, quindi il traffico viene gestito da entrambe le istanze. Dopo la disconnessione di tutti i client esistenti, il sistema tornerà alla situazione normale (figura 1).

Per implementare un'architettura a disponibilità elevata tra più aree sono disponibili due modelli principali:

  1. Il primo consiste nell'usare una coppia di server app e istanza del servizio SignalR che gestisce tutto il traffico online e un'altra coppia come backup (modello denominato attivo/passivo, illustrato nella figura 1).
  2. L'altro consiste nell'usare due o più coppie di server app e istanze del servizio SignalR, ognuna delle quali gestisce parte del traffico online e funge da backup per altre coppie (modello denominato attivo/attivo, simile alla figura 3).

Il servizio SignalR può supportare entrambi i modelli. La differenza principale risiede nel modo in cui vengono implementati i server app. In caso di server app attivi/passivi, anche il servizio SignalR è attivo/passivo, perché il server app primario restituisce solo la propria istanza primaria del servizio SignalR. In caso di server app attivi/attivi, anche il servizio SignalR è attivo/attivo, perché tutti i server app restituiscono le rispettive istanze del servizio SignalR e tutte le istanze possono quindi ricevere traffico.

Si noti che, indipendentemente dai modelli che si sceglie di usare, ogni istanza del servizio SignalR deve essere connessa come primaria a un server app.

Dato che la connessione di SignalR è una connessione lunga, inoltre, i client subiscono interruzioni delle connessioni in caso di emergenza e failover. È necessario gestire questi casi sul lato client in modo che siano trasparenti per i clienti finali. ad esempio eseguendo la riconnessione dopo la chiusura di una connessione.

Come testare un failover

Seguire la procedura per attivare il failover:

  1. Nella scheda Rete della risorsa primaria nel portale disabilitare l'accesso alla rete pubblica. Se la risorsa ha abilitato la rete privata, usare le regole di controllo di accesso per negare tutto il traffico.
  2. Riavviare la risorsa primaria.

Passaggi successivi

Questo articolo ha illustrato come configurare l'applicazione per ottenere la resilienza per il servizio SignalR. Per altre informazioni dettagliate sulla connessione client/server e il routing di connessione nel servizio SignalR, vedere questo articolo relativo agli elementi interni del servizio SignalR.

Per scenari di ridimensionamento, ad esempio il partizionamento orizzontale che usa più istanze insieme per gestire un numero elevato di connessioni, vedere come ridimensionare più istanze.

Per informazioni dettagliate su come configurare Funzioni di Azure con più istanze del servizio SignalR, vedere il supporto per più istanze del servizio Azure SignalR in Funzioni di Azure.