Skala SignalR Service med flera instanser
SignalR Service SDK stöder flera slutpunkter för SignalR Service-instanser. Du kan använda den här funktionen för att skala de samtidiga anslutningarna eller använda den för meddelanden mellan regioner.
För ASP.NET Core
Lägga till flera slutpunkter från konfigurationen
Konfigurera med nyckel Azure:SignalR:ConnectionString
eller Azure:SignalR:ConnectionString:
för SignalR Service-anslutningssträng.
Om nyckeln börjar med Azure:SignalR:ConnectionString:
ska den vara i formatet Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, där Name
och EndpointType
är egenskaperna för ServiceEndpoint
objektet och är tillgängliga från kod.
Du kan lägga till flera instanser anslutningssträng med hjälp av följande dotnet
kommandon:
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>
Lägga till flera slutpunkter från kod
En ServiceEndpoint
klass beskriver egenskaperna för en Azure SignalR Service-slutpunkt.
Du kan konfigurera flera instansslutpunkter när du använder Azure SignalR Service SDK via:
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"),
};
});
Anpassa slutpunktsrouter
Som standard använder SDK DefaultEndpointRouter för att hämta slutpunkter.
Standardbeteende
Routning av klientbegäran:
När klienten
/negotiate
är med appservern. Som standard väljer SDK slumpmässigt en slutpunkt från uppsättningen med tillgängliga tjänstslutpunkter.Routning av servermeddelande:
När du skickar ett meddelande till en specifik anslutning och målanslutningen dirigeras till den aktuella servern går meddelandet direkt till den anslutna slutpunkten. Annars skickas meddelandena till varje Azure SignalR-slutpunkt.
Anpassa routningsalgoritm
Du kan skapa en egen router när du har särskilda kunskaper för att identifiera vilka slutpunkter meddelandena ska gå till.
I följande exempel definieras en anpassad router som dirigerar meddelanden med en grupp som börjar med till slutpunkten med east-
namnet 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);
}
}
I följande exempel åsidosätts standardbeteendet för förhandlingar och slutpunkten väljs beroende på appserverns plats.
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
}
}
Glöm inte att registrera routern till DI-containern med hjälp av:
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>")
};
});
För ASP.NET
Lägga till flera slutpunkter från konfigurationen
Konfiguration med nyckel Azure:SignalR:ConnectionString
eller Azure:SignalR:ConnectionString:
för SignalR Service-anslutningssträng.
Om nyckeln börjar med Azure:SignalR:ConnectionString:
ska den vara i format Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, där Name
och EndpointType
är egenskaperna för ServiceEndpoint
objektet och är tillgängliga från kod.
Du kan lägga till flera instanser anslutningssträng i 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>
Lägga till flera slutpunkter från kod
En ServiceEndpoint
klass beskriver egenskaperna för en Azure SignalR Service-slutpunkt.
Du kan konfigurera flera instansslutpunkter när du använder Azure SignalR Service SDK via:
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>"),
}
});
Anpassa en router
Den enda skillnaden mellan ASP.NET SignalR och ASP.NET Core SignalR är http-kontexttypen för GetNegotiateEndpoint
. För ASP.NET SignalR är den av typen IOwinContext .
Följande kod är ett anpassat förhandlingsexempel för 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
}
}
Glöm inte att registrera routern till DI-containern med hjälp av:
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ått för tjänstslutpunkt
För att aktivera en avancerad router tillhandahåller SignalR Server SDK flera mått som hjälper servern att fatta smarta beslut. Egenskaperna finns under ServiceEndpoint.EndpointMetrics
.
Måttnamn | beskrivning |
---|---|
ClientConnectionCount |
Totalt antal samtidiga klientanslutningar på alla hubbar för tjänstslutpunkten |
ServerConnectionCount |
Totalt antal samtidiga serveranslutningar på alla hubbar för tjänstslutpunkten |
ConnectionCapacity |
Total anslutningskvot för tjänstslutpunkten, inklusive klient- och serveranslutningar |
Följande kod är ett exempel på hur du anpassar en router enligt 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
}
}
ServiceEndpoints för dynamisk skalning
Från SDK version 1.5.0 aktiverar vi ServiceEndpoints i dynamisk skala för ASP.NET Core-versionen först. Så du behöver inte starta om appservern när du behöver lägga till/ta bort en ServiceEndpoint. Eftersom ASP.NET Core stöder en standardkonfiguration som appsettings.json
med reloadOnChange: true
behöver du inte ändra kod och den stöds av naturen. Och om du vill lägga till en anpassad konfiguration och arbeta med frekvent omläsning läser du in konfigurationen i ASP.NET Core.
Kommentar
Med tanke på tiden för anslutningen mellan server/tjänst och klient/tjänst kan vara annorlunda, för att säkerställa att inga meddelandeförluster uppstår under skalningsprocessen, har vi en mellanlagringsperiod som väntar på att serveranslutningarna ska vara klara innan den nya ServiceEndpoint öppnas för klienter. Vanligtvis tar det några sekunder att slutföra och du kan se ett loggmeddelande som Succeed in adding endpoint: '{endpoint}'
anger att processen är klar.
I vissa förväntade situationer, till exempel problem med nätverk mellan regioner eller inkonsekvenser i konfigurationen på olika appservrar, kanske mellanlagringsperioden inte slutförs korrekt. I dessa fall rekommenderar vi att du startar om appservern när du upptäcker att skalningsprocessen inte fungerar korrekt.
Standardtidsgränsen för skalan är 5 minuter och kan anpassas genom att ändra värdet i ServiceOptions.ServiceScaleTimeout
. Om du har många appservrar föreslås det att du utökar värdet lite mer.
Konfiguration i scenarier mellan regioner
Objektet ServiceEndpoint
har en EndpointType
egenskap med värdet primary
eller secondary
.
Primära slutpunkter är prioriterade slutpunkter för att ta emot klienttrafik eftersom de har mer tillförlitliga nätverksanslutningar. Sekundära slutpunkter har mindre tillförlitliga nätverksanslutningar och används endast för server-till-klienttrafik. Till exempel används sekundära slutpunkter för att sända meddelanden i stället för klient till servertrafik.
I fall mellan regioner kan nätverket vara instabilt. För en appserver i USA, östra är primary
SignalR Service-slutpunkten i samma region usa, östra och slutpunkter i andra regioner markerade som secondary
. I den här konfigurationen kan tjänstslutpunkter i andra regioner ta emot meddelanden från den här appservern usa, östra , men inga klienter mellan regioner dirigeras till den här appservern. Följande diagram visar arkitekturen:
När en klient försöker /negotiate
med appservern med en standardrouter väljer SDK:et slumpmässigt en slutpunkt från uppsättningen tillgängliga primary
slutpunkter. När den primära slutpunkten inte är tillgänglig väljer SDK:t slumpmässigt från alla tillgängliga secondary
slutpunkter. Slutpunkten markeras som tillgänglig när anslutningen mellan servern och tjänstslutpunkten är aktiv.
I ett scenario mellan regioner, när en klient försöker /negotiate
med appservern i USA, östra, returnerar den som standard alltid slutpunkten primary
som finns i samma region. När alla slutpunkter i USA , östra inte är tillgängliga omdirigerar routern klienten till slutpunkter i andra regioner. I följande redundansavsnitt beskrivs scenariot i detalj.
Redundans
När ingen primary
slutpunkt är tillgänglig väljer klienten /negotiate
från de tillgängliga secondary
slutpunkterna. Den här redundansmekanismen kräver att varje slutpunkt fungerar som en primary
slutpunkt till minst en appserver.
Nästa steg
Du kan använda flera slutpunkter i scenarier med hög tillgänglighet och haveriberedskap.