Mettre à l’échelle SignalR Service avec plusieurs instances
Le SDK de SignalR Service prend en charge plusieurs points de terminaison pour les instances de SignalR Service. Vous pouvez utiliser cette fonctionnalité pour la messagerie multirégion ou pour mettre à l’échelle des connexions simultanées.
Pour ASP.NET Core
Ajouter plusieurs points de terminaison à partir de la configuration
Configurez avec la clé Azure:SignalR:ConnectionString
ou Azure:SignalR:ConnectionString:
pour signalR Service chaîne de connexion.
Si la clé commence par Azure:SignalR:ConnectionString:
, elle doit être au format Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, où Name
et EndpointType
sont des propriétés de l’objet ServiceEndpoint
et sont accessibles à partir du code.
Vous pouvez ajouter plusieurs chaînes de connexion d’instance à l’aide des commandes dotnet
suivantes :
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>
Ajouter plusieurs points de terminaison à partir du code
Une ServicEndpoint
classe décrit les propriétés d’un point de terminaison Azure SignalR Service.
Vous pouvez configurer plusieurs points de terminaison d’instance quand vous utilisez le SDK de Service Azure SignalR au moyen du code suivant :
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"),
};
});
Personnaliser le routeur de point de terminaison
Par défaut, le SDK utilise le DefaultEndpointRouter pour sélectionner les points de terminaison.
Comportement par défaut
Routage des demandes du client :
Quand le client négocie (
/negotiate
) avec le serveur d’applications, par défaut, le SDK sélectionne de manière aléatoire un point de terminaison dans l’ensemble de points de terminaison de service disponibles.Routage des messages serveur :
Lors de l’envoi d’un message à une connexion spécifique et que la connexion cible est acheminée vers le serveur actuel, le message passe directement à ce point de terminaison connecté. Sinon, les messages sont diffusés à chaque point de terminaison Azure SignalR.
Personnaliser l’algorithme de routage
Vous pouvez créer votre propre routeur si vous avez suffisamment de connaissances pour identifier les points de terminaison vers lesquels les messages doivent être envoyés.
L’exemple suivant définit un routeur personnalisé qui route les messages avec un groupe commençant par east-
le point de terminaison nommé 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);
}
}
L’exemple suivant remplace le comportement de négociation par défaut et sélectionne le point de terminaison en fonction de l’emplacement du serveur d’applications.
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
}
}
N’oubliez pas d’inscrire le routeur sur le conteneur d’injection de dépendances comme suit :
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>")
};
});
Pour ASP.NET
Ajouter plusieurs points de terminaison à partir de la configuration
Configuration avec la clé Azure:SignalR:ConnectionString
ou Azure:SignalR:ConnectionString:
pour signalR Service chaîne de connexion.
Si la clé commence par Azure:SignalR:ConnectionString:
, elle doit être au format Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, où Name
et EndpointType
sont des propriétés de l’objet ServiceEndpoint
et sont accessibles à partir du code.
Vous pouvez ajouter plusieurs chaînes de connexion d’instance à 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>
Ajouter plusieurs points de terminaison à partir du code
Une ServiceEndpoint
classe décrit les propriétés d’un point de terminaison Azure SignalR Service.
Vous pouvez configurer plusieurs points de terminaison d’instance quand vous utilisez le SDK de Service Azure SignalR au moyen du code suivant :
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>"),
}
});
Personnaliser un routeur
La seule différence entre ASP.NET SignalR et ASP.NET Core SignalR est le type de contexte http pour GetNegotiateEndpoint
. Pour ASP.NET SignalR, il s’agit du type IOwinContext.
Le code suivant est un exemple de négociation personnalisé pour 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
}
}
N’oubliez pas d’inscrire le routeur sur le conteneur d’injection de dépendances comme suit :
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>")
};
});
Métriques de point de terminaison de service
Pour activer un routeur avancé, le Kit de développement logiciel (SDK) du serveur SignalR fournit plusieurs métriques pour aider le serveur à prendre des décisions intelligentes. Les propriétés sont sous ServiceEndpoint.EndpointMetrics
.
Nom de métrique | Description |
---|---|
ClientConnectionCount |
Nombre total de connexions clientes simultanées sur tous les hubs pour le point de terminaison de service |
ServerConnectionCount |
Nombre total de connexions de serveur simultanées sur tous les hubs pour le point de terminaison de service |
ConnectionCapacity |
Quota total de connexions pour le point de terminaison de service, y compris les connexions client et serveur |
Le code suivant est un exemple de personnalisation d’un routeur en fonction de 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
}
}
Points de terminaison de service de mise à l’échelle dynamique
À partir du kit de développement logiciel (SDK) version 1.5.0, nous allons commencer par activer les points de terminaison de service à l’échelle dynamique pour ASP.NET Core. Vous n’avez donc pas à redémarrer le serveur d’application lorsque vous devez ajouter/supprimer un point de terminaison de service. Comme ASP.NET Core prend en charge la configuration par défaut, comme appsettings.json
avec reloadOnChange: true
, vous n’avez pas besoin de modifier le code, qui est pris en charge par nature. Et si vous souhaitez ajouter une configuration personnalisée et utiliser un rechargement à chaud, reportez-vous à Configuration dans ASP.NET Core.
Remarque
Compte tenu de l’heure de configuration de la connexion entre le serveur/le service et le client/service peut être différent, afin de ne pas perdre de message pendant le processus de mise à l’échelle, nous avons une période de préproduction qui attend que les connexions de serveur soient prêtes avant d’ouvrir le nouveau ServiceEndpoint aux clients. En règle générale, il faut des secondes et vous serez en mesure de voir un message de journal comme Succeed in adding endpoint: '{endpoint}'
celui qui indique la fin du processus.
Dans certaines situations attendues, telles que les problèmes réseau interrégions ou les incohérences de configuration sur différents serveurs d’applications, la période de préproduction peut ne pas se terminer correctement. Dans ces cas, il est recommandé de redémarrer le serveur d’applications lorsque vous trouvez que le processus de mise à l’échelle ne fonctionne pas correctement.
La période d’expiration par défaut de l’échelle est de 5 minutes, et elle peut être personnalisée en modifiant la valeur dans ServiceOptions.ServiceScaleTimeout
. Si vous avez beaucoup de serveurs d’application, il est suggéré d’étendre la valeur un peu plus.
Configuration dans les scénarios inter-régions
L’objet ServiceEndpoint
a une propriété EndpointType
avec la valeur primary
ou secondary
.
Les points de terminaison principaux sont des points de terminaison préférés pour recevoir le trafic client, car ils ont des connexions réseau plus fiables. Les points de terminaison secondaires disposent de connexions réseau moins fiables et sont utilisés uniquement pour le serveur vers le trafic client. Par exemple, les points de terminaison secondaires sont utilisés pour diffuser des messages au lieu du trafic client vers le serveur.
Dans les cas interrégions, le réseau peut être instable. Pour un serveur d’applications situé dans la région USA Est, le point de terminaison SignalR Service situé dans la même région USA Est est primary
et les points de terminaison dans d’autres régions marquées comme secondary
. Dans cette configuration, les points de terminaison de service d’autres régions peuvent recevoir des messages de ce serveur d’applications USA Est, mais aucun client interrégion n’est acheminé vers ce serveur d’applications. Le diagramme suivant présente l’architecture :
Lorsqu’un client tente /negotiate
avec le serveur d’applications avec un routeur par défaut, le SDK sélectionne de façon aléatoire un point de terminaison dans l’ensemble de points de terminaison disponibles primary
. Lorsque le point de terminaison principal n’est pas disponible, le Kit de développement logiciel (SDK ) sélectionne de manière aléatoire tous les points de terminaison disponibles secondary
. Le point de terminaison est marqué comme disponible quand la connexion entre le serveur et le point de terminaison de service est active.
Dans un scénario interrégion, lorsqu’un client tente /negotiate
avec le serveur d’applications hébergé dans la région USA Est, par défaut, il retourne toujours le primary
point de terminaison situé dans la même région. Lorsque tous les points de terminaison USA Est ne sont pas disponibles, le routeur redirige le client vers des points de terminaison dans d’autres régions. La section de basculement suivante décrit le scénario en détail.
Type de basculement
Lorsqu’aucun point de terminaison n’est primary
/negotiate
disponible, le client choisit parmi les points de terminaison disponibles secondary
. Ce mécanisme de basculement nécessite que chaque point de terminaison sert de primary
point de terminaison à au moins un serveur d’applications.
Étapes suivantes
Vous pouvez utiliser plusieurs points de terminaison dans des scénarios de haute disponibilité et de récupération d’urgence.