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.
Important
Des chaînes de connexion brutes sont utilisées dans cet article uniquement à des fins de démonstration.
Une chaîne de connexion contient les informations d’autorisation requises pour que votre application accède au service Azure Web PubSub. La clé d’accès à l’intérieur dans la chaîne de connexion est semblable à un mot de passe racine pour votre service. Dans les environnements de production, protégez toujours vos clés d’accès. Utilisez Azure Key Vault pour gérer et permuter vos clés de façon sécurisée, sécuriser votre chaîne de connexion en utilisant Microsoft Entra ID et autoriser l’accès avec Microsoft Entra ID.
Évitez de distribuer des clés d’accès à d’autres utilisateurs, de les coder en dur ou de les enregistrer en texte brut dans un emplacement accessible à d’autres personnes. Effectuez une rotation de vos clés si vous pensez qu’elles ont pu être compromises.
Pour ASP.NET Core
Ajouter plusieurs points de terminaison à partir de la configuration
Des chaînes de connexion brutes sont utilisées dans cet article à des fins de démonstration uniquement. Dans les environnements de production, protégez toujours vos clés d’accès. Utilisez Azure Key Vault pour gérer et permuter vos clés de façon sécurisée, sécuriser votre chaîne de connexion en utilisant Microsoft Entra ID et autoriser l’accès avec Microsoft Entra ID.
Effectuez la configuration avec la clé Azure:SignalR:ConnectionString
ou Azure:SignalR:ConnectionString:
pour la chaîne de connexion de SignalR Service.
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 classe ServiceEndpoint
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 de serveur :
Quand un message est envoyé à une connexion spécifique et que la connexion cible est acheminée vers le serveur actuel, le message parvient directement à ce point de terminaison connectée. 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-
vers 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)
{
// Sample code showing how to choose endpoints based on the incoming request endpoint query
var endpointName = context.Request.Query["endpoint"].FirstOrDefault() ?? "";
// Select from the available endpoints, don't construct a new ServiceEndpoint object here
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>")
};
});
ServiceOptions.Endpoints
prend également en charge le rechargement à chaud. L’exemple de code ci-dessous montre comment charger des chaînes de connexion à partir d’une section de configuration et d’une URL publique exposées par des proxys inverses à partir d’un autre. Tant que la configuration prend en charge le rechargement à chaud, les points de terminaison peuvent être mis à jour à la volée.
services.Configure<ServiceOptions>(o =>
{
o.Endpoints = [
new ServiceEndpoint(Configuration["ConnectionStrings:AzureSignalR:East"], name: "east")
{
ClientEndpoint = new Uri(Configuration.GetValue<string>("PublicClientEndpoints:East"))
},
new ServiceEndpoint(Configuration["ConnectionStrings:AzureSignalR:West"], name: "west")
{
ClientEndpoint = new Uri(Configuration.GetValue<string>("PublicClientEndpoints:West"))
},
];
});
Pour ASP.NET
Ajouter plusieurs points de terminaison à partir de la configuration
Configuration avec la clé Azure:SignalR:ConnectionString
ou Azure:SignalR:ConnectionString:
pour la chaîne de connexion de SignalR Service.
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 classe ServiceEndpoint
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)
{
// Sample code showing how to choose endpoints based on the incoming request endpoint query
var endpointName = context.Request.Query["endpoint"] ?? "";
// Select from the available endpoints, don't construct a new ServiceEndpoint object here
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
Étant donné que le temps d’établissement de la connexion entre le serveur/service et le client/service peut être différent, pour garantir qu’il n’y a pas de perte de messages pendant le processus de mise à l’échelle, nous avons une période d’attente pour que les connexions du serveur soient prêtes avant d’ouvrir le nouveau point de terminaison de service aux clients. En règle générale, l’exécution du processus prend quelques secondes et vous serez en mesure de voir un message de journal comme Succeed in adding endpoint: '{endpoint}'
, qui indique que le processus est terminé.
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.
Remarque
Actuellement, la fonctionnalité de points de terminaison multiples est uniquement prise en charge sur le type de transport Persistent
.
Pour les extensions SignalR Functions
Configuration
Pour activer plusieurs instances SignalR Service, vous devez :
Utiliser le type de transport
Persistent
.Le type de transport par défaut est le mode
Transient
. Vous devez ajouter l’entrée suivante à votre fichierlocal.settings.json
ou au paramètre d’application sur Azure.{ "AzureSignalRServiceTransportType":"Persistent" }
Remarque
Lorsque vous passez du mode
Transient
au modePersistent
, vous pouvez constater un changement de comportement de la sérialisation JSON. En effet, dans le modeTransient
, la bibliothèqueNewtonsoft.Json
est utilisée pour sérialiser les arguments des méthodes de hub, alors que dans le modePersistent
, la bibliothèqueSystem.Text.Json
est utilisée par défaut.System.Text.Json
présente certaines différences clés dans le comportement par défaut avecNewtonsoft.Json
. Si vous souhaitez utiliserNewtonsoft.Json
en modePersistent
, vous pouvez ajouter un élément de configuration :"Azure:SignalR:HubProtocol":"NewtonsoftJson"
dans le fichierlocal.settings.json
ouAzure__SignalR__HubProtocol=NewtonsoftJson
sur le Portail Azure.Configurer plusieurs entrées de points de terminaison SignalR Service dans votre configuration.
Nous utilisons un objet
ServiceEndpoint
pour représenter une instance SignalR Service. Vous pouvez définir un point de terminaison de service avec son<EndpointName>
et son<EndpointType>
dans la clé d’entrée, et la chaîne de connexion dans la valeur d’entrée. Les clés sont au format suivant :Azure:SignalR:Endpoints:<EndpointName>:<EndpointType>
<EndpointType>
est facultatif et est défini par défaut surprimary
. Consultez les exemples ci-dessous :{ "Azure:SignalR:Endpoints:EastUs":"<ConnectionString>", "Azure:SignalR:Endpoints:EastUs2:Secondary":"<ConnectionString>", "Azure:SignalR:Endpoints:WestUs:Primary":"<ConnectionString>" }
Remarque
Lorsque vous configurez des points de terminaison Azure SignalR dans App Service sur le Portail Azure, n’oubliez pas de remplacer
":"
par"__"
(double trait de soulignement dans les clés). Pour savoir pourquoi, consultez Variables d’environnement.La chaîne de connexion configurée avec la clé
{ConnectionStringSetting}
(par défaut, « AzureSignalRConnectionString ») est également reconnue comme point de terminaison de service principal avec un nom vide. Toutefois, ce style de configuration n’est pas recommandé pour plusieurs points de terminaison.
Routage
Comportement par défaut
Par défaut, la liaison de fonctions utilise le DefaultEndpointRouter pour sélectionner les points de terminaison.
Routage du client : sélectionnez de façon aléatoire un point de terminaison parmi les points de terminaison en ligne principaux. Si tous les points de terminaison principaux sont hors connexion, sélectionnez aléatoirement un point de terminaison en ligne secondaire. Si la sélection échoue à nouveau, l’exception est levée.
Routage des messages serveur : tous les points de terminaison de service sont retournés.
Personnalisation
Modèle in-process C#
Voici les étapes à suivre :
Implémentez un routeur personnalisé. Vous pouvez tirer parti des informations fournies par
ServiceEndpoint
pour prendre une décision de routage. Consultez le guide ici : customize-route-algorithm. Notez que le déclencheur HTTP est requis dans la fonction de négociation lorsque vous avez besoin deHttpContext
dans la méthode de négociation personnalisée.Inscrivez le routeur dans le conteneur DI.
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Azure.SignalR;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(SimpleChatV3.Startup))]
namespace SimpleChatV3
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddSingleton<IEndpointRouter, CustomizedRouter>();
}
}
}
Modèle de processus isolé
Pour les fonctions s’exécutant sur un modèle de processus isolé, nous prenons en charge la spécification des points de terminaison cibles dans chaque requête. Vous utiliserez de nouveaux types de liaison pour obtenir des informations sur le point de terminaison.
Acheminement client
La liaison SignalRConnectionInfo
sélectionne un point de terminaison en fonction de la règle de routage par défaut. Si vous souhaitez personnaliser la règle de routage, vous devez utiliser la liaison SignalRNegotiation
au lieu de la liaison SignalRConnectionInfo
.
Les propriétés de configuration de la liaison SignalRNegotiation
sont identiques à celles de SignalRConnectionInfo
. Voici un exemple de fichier function.json
:
{
"type": "signalRNegotiation",
"name": "negotiationContext",
"hubName": "<HubName>",
"direction": "in"
}
Vous pouvez également ajouter d’autres données de liaison telles que userId
, idToken
et claimTypeList
tout comme SignalRConnectionInfo
.
L’objet que vous obtenez à partir de la liaison SignalRNegotiation
est au format suivant :
{
"endpoints": [
{
"endpointType": "Primary",
"name": "<EndpointName>",
"endpoint": "https://****.service.signalr.net",
"online": true,
"connectionInfo": {
"url": "<client-access-url>",
"accessToken": "<client-access-token>"
}
},
{
"...": "..."
}
]
}
Voici un exemple d’utilisation JavaScript de la liaison SignalRNegotiation
:
module.exports = function (context, req, negotiationContext) {
var userId = req.query.userId;
if (userId.startsWith("east-")) {
//return the first endpoint whose name starts with "east-" and status is online.
context.res.body = negotiationContext.endpoints.find(endpoint => endpoint.name.startsWith("east-") && endpoint.online).connectionInfo;
}
else {
//return the first online endpoint
context.res.body = negotiationContext.endpoints.filter(endpoint => endpoint.online)[0].connectionInfo;
}
}
Routage des messages
Le routage des messages ou des actions nécessite la coopération de deux types de liaisons. En général, vous avez besoin d’un nouveau type SignalREndpoints
de liaison d’entrée pour obtenir toutes les informations de point de terminaison disponibles. Ensuite, vous filtrez les points de terminaison et obtenez un tableau contenant tous les points de terminaison auxquels vous souhaitez envoyer. Enfin, vous spécifiez les points de terminaison cibles dans la liaison de sortie SignalR
.
Voici les propriétés de configuration de la liaison SignalREndpoints
dans le fichier functions.json
:
{
"type": "signalREndpoints",
"direction": "in",
"name": "endpoints",
"hubName": "<HubName>"
}
L’objet que vous obtenez de SignalREndpoints
est un tableau de points de terminaison dont chacun est représenté en tant qu’objet JSON selon le schéma suivant :
{
"endpointType": "<EndpointType>",
"name": "<EndpointName>",
"endpoint": "https://****.service.signalr.net",
"online": true
}
Après avoir obtenu le tableau des points de terminaison cible, ajoutez une propriété endpoints
à l’objet de liaison de sortie. Voici un exemple JavaScript :
module.exports = function (context, req, endpoints) {
var targetEndpoints = endpoints.filter(endpoint => endpoint.name.startsWith("east-"));
context.bindings.signalRMessages = [{
"target": "chat",
"arguments": ["hello-world"],
"endpoints": targetEndpoints,
}];
context.done();
}
Pour le kit de développement logiciel (SDK) Management
Ajouter plusieurs points de terminaison à partir de la configuration
Effectuez la configuration avec la clé Azure:SignalR:Endpoints
pour la chaîne de connexion SignalR Service. La clé doit être au format Azure:SignalR:Endpoints:{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: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>
Ajouter plusieurs points de terminaison à partir du code
Une classe ServiceEndpoint
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 kit SDK Azure SignalR Management à l’aide du code suivant :
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();
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 de serveur :
Quand un message est envoyé à une connexion spécifique et que la connexion cible est acheminée vers le serveur actuel, le message parvient directement à ce point de terminaison connectée. 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-
vers 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 :
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"),
};
})
.WithRouter(new CustomRouter())
.BuildServiceManager();
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 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 dans les autres régions peuvent recevoir les messages de ce serveur d’applications USA Est, mais aucun client inter-régions n’est routé vers ce serveur d’applications. Le diagramme suivant présente l’architecture :
Quand un client tente de négocier (/negotiate
) avec le serveur d’applications, avec un routeur par défaut, le SDK sélectionne de manière aléatoire un point de terminaison dans l’ensemble de points de terminaison primary
disponibles. Si le point de terminaison principal n’est pas disponible, le SDK effectue alors une sélection aléatoire parmi tous les points de terminaison secondary
disponibles. 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 multirégion, quand un client tente de négocier (/negotiate
) avec le serveur d’applications hébergé dans la région USA Est, par défaut, il retourne toujours le point de terminaison primary
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.
Basculement
Lorsqu’aucun point de terminaison primary
n’est disponible, le /negotiate
du client choisit parmi les points de terminaison secondary
disponibles. Ce mécanisme de basculement demande que chaque point de terminaison fasse office de point de terminaison primary
sur 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.