Ridimensionare Servizio SignalR con più istanze
Servizio SignalR SDK supporta più endpoint per le istanze di Servizio SignalR. È possibile usare questa funzionalità per ridimensionare le connessioni simultanee o usarla per la messaggistica tra aree.
Per ASP.NET Core
Aggiungere più endpoint dalla configurazione
Configurare con la chiave Azure:SignalR:ConnectionString
o Azure:SignalR:ConnectionString:
per Servizio SignalR stringa di connessione.
Se la chiave inizia con Azure:SignalR:ConnectionString:
, deve essere nel formato Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, dove Name
e EndpointType
sono proprietà dell'oggetto ServiceEndpoint
e sono accessibili dal codice.
È possibile aggiungere più stringa di connessione di istanza usando i comandi seguentidotnet
:
dotnet user-secrets set Azure:SignalR:ConnectionString:east-region-a <ConnectionString1>
dotnet user-secrets set Azure:SignalR:ConnectionString:east-region-b:primary <ConnectionString2>
dotnet user-secrets set Azure:SignalR:ConnectionString:backup:secondary <ConnectionString3>
Aggiungere più endpoint dal codice
Una ServiceEndpoint
classe descrive le proprietà di un endpoint Servizio Azure SignalR.
È possibile configurare più endpoint di istanza quando si usa Servizio Azure SignalR SDK tramite:
services.AddSignalR()
.AddAzureSignalR(options =>
{
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"),
};
});
Personalizzare il router endpoint
Per impostazione predefinita, l'SDK usa DefaultEndpointRouter per prelevare gli endpoint.
Comportamento predefinito
Routing delle richieste client:
Quando il client
/negotiate
con il server app. Per impostazione predefinita, SDK seleziona in modo casuale un endpoint dal set di endpoint di servizio disponibili.Routing dei messaggi del server:
Quando si invia un messaggio a una connessione specifica e la connessione di destinazione viene instradata al server corrente, il messaggio passa direttamente all'endpoint connesso. In caso contrario, i messaggi vengono trasmessi a ogni endpoint di Azure SignalR.
Personalizzare l'algoritmo di routing
È possibile creare un router personalizzato quando si hanno conoscenze speciali per identificare gli endpoint a cui devono essere inviati i messaggi.
L'esempio seguente definisce un router personalizzato che instrada i messaggi con un gruppo a partire dall'endpoint east-
denominato east
:
private class CustomRouter : EndpointRouterDecorator
{
public override IEnumerable<ServiceEndpoint> GetEndpointsForGroup(string groupName, IEnumerable<ServiceEndpoint> endpoints)
{
// Override the group broadcast behavior, if the group name starts with "east-", only send messages to endpoints inside east
if (groupName.StartsWith("east-"))
{
return endpoints.Where(e => e.Name.StartsWith("east-"));
}
return base.GetEndpointsForGroup(groupName, endpoints);
}
}
Nell'esempio seguente viene eseguito l'override del comportamento di negoziazione predefinito e viene selezionato l'endpoint a seconda del percorso del server app.
private class CustomRouter : EndpointRouterDecorator
{ public override ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable<ServiceEndpoint> endpoints)
{
// Override the negotiate behavior to get the endpoint from query string
var endpointName = context.Request.Query["endpoint"];
if (endpointName.Count == 0)
{
context.Response.StatusCode = 400;
var response = Encoding.UTF8.GetBytes("Invalid request");
context.Response.Body.Write(response, 0, response.Length);
return null;
}
return endpoints.FirstOrDefault(s => s.Name == endpointName && s.Online) // Get the endpoint with name matching the incoming request
?? base.GetNegotiateEndpoint(context, endpoints); // Or fallback to the default behavior to randomly select one from primary endpoints, or fallback to secondary when no primary ones are online
}
}
Non dimenticare di registrare il router nel contenitore di inserimento delle dipendenze usando:
services.AddSingleton(typeof(IEndpointRouter), typeof(CustomRouter));
services.AddSignalR()
.AddAzureSignalR(
options =>
{
options.Endpoints = new ServiceEndpoint[]
{
new ServiceEndpoint(name: "east", connectionString: "<connectionString1>"),
new ServiceEndpoint(name: "west", connectionString: "<connectionString2>"),
new ServiceEndpoint("<connectionString3>")
};
});
Per ASP.NET
Aggiungere più endpoint dalla configurazione
Configurazione con chiave Azure:SignalR:ConnectionString
o Azure:SignalR:ConnectionString:
per Servizio SignalR stringa di connessione.
Se la chiave inizia con Azure:SignalR:ConnectionString:
, deve essere nel formato Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, dove Name
e EndpointType
sono proprietà dell'oggetto ServiceEndpoint
e sono accessibili dal codice.
È possibile aggiungere più stringa di connessione di istanza a web.config
:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="Azure:SignalR:ConnectionString" connectionString="<ConnectionString1>"/>
<add name="Azure:SignalR:ConnectionString:en-us" connectionString="<ConnectionString2>"/>
<add name="Azure:SignalR:ConnectionString:zh-cn:secondary" connectionString="<ConnectionString3>"/>
<add name="Azure:SignalR:ConnectionString:Backup:secondary" connectionString="<ConnectionString4>"/>
</connectionStrings>
...
</configuration>
Aggiungere più endpoint dal codice
Una ServiceEndpoint
classe descrive le proprietà di un endpoint Servizio Azure SignalR.
È possibile configurare più endpoint di istanza quando si usa Servizio Azure SignalR SDK tramite:
app.MapAzureSignalR(
this.GetType().FullName,
options => {
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("<ConnectionString1>"),
new ServiceEndpoint("<ConnectionString2>"),
new ServiceEndpoint("<ConnectionString3>"),
}
});
Personalizzare un router
L'unica differenza tra ASP.NET SignalR e ASP.NET Core SignalR è il tipo di contesto http per GetNegotiateEndpoint
. Per ASP.NET SignalR, è di tipo IOwinContext .
Il codice seguente è un esempio di negoziazione personalizzato per ASP.NET SignalR:
private class CustomRouter : EndpointRouterDecorator
{
public override ServiceEndpoint GetNegotiateEndpoint(IOwinContext context, IEnumerable<ServiceEndpoint> endpoints)
{
// Override the negotiate behavior to get the endpoint from query string
var endpointName = context.Request.Query["endpoint"];
if (string.IsNullOrEmpty(endpointName))
{
context.Response.StatusCode = 400;
context.Response.Write("Invalid request.");
return null;
}
return endpoints.FirstOrDefault(s => s.Name == endpointName && s.Online) // Get the endpoint with name matching the incoming request
?? base.GetNegotiateEndpoint(context, endpoints); // Or fallback to the default behavior to randomly select one from primary endpoints, or fallback to secondary when no primary ones are online
}
}
Non dimenticare di registrare il router nel contenitore di inserimento delle dipendenze usando:
var hub = new HubConfiguration();
var router = new CustomRouter();
hub.Resolver.Register(typeof(IEndpointRouter), () => router);
app.MapAzureSignalR(GetType().FullName, hub, options => {
options.Endpoints = new ServiceEndpoint[]
{
new ServiceEndpoint(name: "east", connectionString: "<connectionString1>"),
new ServiceEndpoint(name: "west", connectionString: "<connectionString2>"),
new ServiceEndpoint("<connectionString3>")
};
});
Metriche degli endpoint di servizio
Per abilitare un router avanzato, SignalR SERVER SDK fornisce più metriche per consentire al server di prendere decisioni intelligenti. Le proprietà sono in ServiceEndpoint.EndpointMetrics
.
Nome misurazione | Descrizione |
---|---|
ClientConnectionCount |
Numero totale di connessioni client simultanee in tutti gli hub per l'endpoint di servizio |
ServerConnectionCount |
Numero totale di connessioni server simultanee in tutti gli hub per l'endpoint di servizio |
ConnectionCapacity |
Quota totale di connessione per l'endpoint di servizio, incluse le connessioni client e server |
Il codice seguente è un esempio di personalizzazione di un router in base a ClientConnectionCount
.
private class CustomRouter : EndpointRouterDecorator
{
public override ServiceEndpoint GetNegotiateEndpoint(HttpContext context, IEnumerable<ServiceEndpoint> endpoints)
{
return endpoints.OrderBy(x => x.EndpointMetrics.ClientConnectionCount).FirstOrDefault(x => x.Online) // Get the available endpoint with minimal clients load
?? base.GetNegotiateEndpoint(context, endpoints); // Or fallback to the default behavior to randomly select one from primary endpoints, or fallback to secondary when no primary ones are online
}
}
Servizio di scalabilità dinamicaEndpoint
A partire dall'SDK versione 1.5.0, è possibile abilitare serviceEndpoint con scalabilità dinamica per ASP.NET versione Core. Non è quindi necessario riavviare il server app quando è necessario aggiungere/rimuovere un ServiceEndpoint. Poiché ASP.NET Core supporta una configurazione predefinita come appsettings.json
con reloadOnChange: true
, non è necessario modificare il codice ed è supportato per natura. Se si vuole aggiungere una configurazione personalizzata e usare il ricaricamento rapido, vedere Configurazione in ASP.NET Core.
Nota
Considerando il tempo di configurazione della connessione tra server/servizio e client/servizio, è possibile che non si verifichi alcuna perdita di messaggi durante il processo di scalabilità, è previsto un periodo di staging in attesa che le connessioni server siano pronte prima di aprire il nuovo ServiceEndpoint ai client. In genere sono necessari secondi per il completamento e sarà possibile visualizzare un messaggio di log simile Succeed in adding endpoint: '{endpoint}'
al quale indica il processo completato.
In alcune situazioni previste, ad esempio problemi di rete tra aree o incoerenze di configurazione in server app diversi, il periodo di gestione temporanea potrebbe non terminare correttamente. In questi casi, è consigliabile riavviare il server app quando il processo di ridimensionamento non funziona correttamente.
Il periodo di timeout predefinito per la scala è di 5 minuti e può essere personalizzato modificando il valore in ServiceOptions.ServiceScaleTimeout
. Se si dispone di un sacco di server app, è consigliabile estendere il valore un po 'di più.
Configurazione in scenari tra aree
L'oggetto ServiceEndpoint
ha una EndpointType
proprietà con valore primary
o secondary
.
Gli endpoint primari sono endpoint preferiti per ricevere traffico client perché hanno connessioni di rete più affidabili. Gli endpoint secondari hanno connessioni di rete meno affidabili e vengono usati solo per il traffico da server a client. Ad esempio, gli endpoint secondari vengono usati per la trasmissione di messaggi anziché per il traffico da client a server.
Nei casi tra aree, la rete può essere instabile. Per un server app che si trova negli Stati Uniti orientali, l'endpoint Servizio SignalR che si trova nella stessa area Stati Uniti orientali è primary
e gli endpoint in altre aree contrassegnate come secondary
. In questa configurazione, gli endpoint di servizio in altre aree possono ricevere messaggi da questo server app Stati Uniti orientali, ma non vengono instradati client tra aree a questo server app. Il diagramma seguente illustra l'architettura:
Quando un client prova /negotiate
con il server app con un router predefinito, l'SDK seleziona in modo casuale un endpoint dal set di endpoint disponibili primary
. Quando l'endpoint primario non è disponibile, l'SDK seleziona in modo casuale da tutti gli endpoint disponibili secondary
. L'endpoint è contrassegnato come disponibile quando la connessione tra il server e l'endpoint di servizio è attiva.
In uno scenario tra aree, quando un client prova /negotiate
con il server app ospitato negli Stati Uniti orientali, per impostazione predefinita restituisce sempre l'endpoint primary
che si trova nella stessa area. Quando tutti gli endpoint degli Stati Uniti orientali non sono disponibili, il router reindirizza il client agli endpoint in altre aree. Nella sezione failover seguente viene descritto in dettaglio lo scenario.
Failover
Quando non è disponibile alcun primary
endpoint, il client /negotiate
sceglie gli endpoint disponibili secondary
. Questo meccanismo di failover richiede che ogni endpoint funzioni come primary
endpoint per almeno un server app.
Passaggi successivi
È possibile usare più endpoint in scenari di disponibilità elevata e ripristino di emergenza.