Skalowanie usługi SignalR Service z wieloma wystąpieniami
Zestaw SDK usługi SignalR Service obsługuje wiele punktów końcowych dla wystąpień usługi SignalR Service. Za pomocą tej funkcji można skalować połączenia współbieżne lub używać jej do obsługi komunikatów między regionami.
Ważne
Nieprzetworzone parametry połączenia są wyświetlane tylko w tym artykule w celach demonstracyjnych.
Parametry połączenia zawiera informacje o autoryzacji wymagane przez aplikację w celu uzyskania dostępu do usługi Azure Web PubSub. Klucz dostępu wewnątrz parametry połączenia jest podobny do hasła głównego usługi. W środowiskach produkcyjnych zawsze chroń klucze dostępu. Usługa Azure Key Vault umożliwia bezpieczne zarządzanie kluczami i obracanie ich oraz zabezpieczanie parametry połączenia przy użyciu identyfikatora Entra firmy Microsoft.
Unikaj dystrybuowania kluczy dostępu do innych użytkowników, kodowania ich lub zapisywania ich w dowolnym miejscu w postaci zwykłego tekstu, który jest dostępny dla innych użytkowników. Obracanie kluczy, jeśli uważasz, że mogły one zostać naruszone.
Dla ASP.NET Core
Dodawanie wielu punktów końcowych z konfiguracji
Nieprzetworzone parametry połączenia są wyświetlane tylko w tym artykule w celach demonstracyjnych. W środowiskach produkcyjnych zawsze chroń klucze dostępu. Usługa Azure Key Vault umożliwia bezpieczne zarządzanie kluczami i obracanie ich oraz zabezpieczanie parametry połączenia przy użyciu identyfikatora Entra firmy Microsoft.
Skonfiguruj przy użyciu klucza Azure:SignalR:ConnectionString
lub Azure:SignalR:ConnectionString:
parametry połączenia usługi SignalR Service.
Jeśli klucz zaczyna się od Azure:SignalR:ConnectionString:
, powinien mieć format Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, gdzie Name
i EndpointType
są właściwościami ServiceEndpoint
obiektu i są dostępne z kodu.
Możesz dodać wiele parametry połączenia wystąpień przy użyciu następujących dotnet
poleceń:
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>
Dodawanie wielu punktów końcowych z kodu
Klasa ServiceEndpoint
opisuje właściwości punktu końcowego usługi Azure SignalR Service.
Możesz skonfigurować wiele punktów końcowych wystąpienia podczas korzystania z zestawu SDK usługi Azure SignalR Service za pomocą:
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"),
};
});
Dostosowywanie routera punktu końcowego
Domyślnie zestaw SDK używa elementu DefaultEndpointRouter do odbierania punktów końcowych.
Zachowanie domyślne
Routing żądań klienta:
Gdy klient
/negotiate
z serwerem aplikacji. Domyślnie zestaw SDK losowo wybiera jeden punkt końcowy z zestawu dostępnych punktów końcowych usługi.Routing komunikatów serwera:
Podczas wysyłania komunikatu do określonego połączenia , a połączenie docelowe jest kierowane do bieżącego serwera, komunikat przechodzi bezpośrednio do tego połączonego punktu końcowego. W przeciwnym razie komunikaty są emitowane do każdego punktu końcowego usługi Azure SignalR.
Dostosowywanie algorytmu routingu
Możesz utworzyć własny router, gdy masz specjalną wiedzę, aby określić, do których punktów końcowych powinny przejść komunikaty.
W poniższym przykładzie zdefiniowano router niestandardowy, który kieruje komunikaty grupą rozpoczynającą east-
się od punktu końcowego o nazwie 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);
}
}
Poniższy przykład zastępuje domyślne zachowanie negocjowania i wybiera punkt końcowy w zależności od lokalizacji serwera aplikacji.
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
}
}
Nie zapomnij zarejestrować routera w kontenerze DI przy użyciu:
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
obsługuje również przeładowywanie na gorąco. Poniższy przykładowy kod pokazuje, jak załadować parametry połączenia z jednej sekcji konfiguracji i publiczny adres URL uwidoczniony przez odwrotne serwery proxy z innego, o ile konfiguracja obsługuje ponowne ładowanie na gorąco, punkty końcowe mogą być aktualizowane na bieżąco.
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"))
},
];
});
W przypadku ASP.NET
Dodawanie wielu punktów końcowych z konfiguracji
Konfiguracja przy użyciu klucza Azure:SignalR:ConnectionString
lub Azure:SignalR:ConnectionString:
parametry połączenia usługi SignalR Service.
Jeśli klucz zaczyna się od Azure:SignalR:ConnectionString:
, powinien mieć format Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, gdzie Name
i EndpointType
są właściwościami ServiceEndpoint
obiektu i są dostępne z kodu.
Do pliku można dodać wiele parametry połączenia wystąpień: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>
Dodawanie wielu punktów końcowych z kodu
Klasa ServiceEndpoint
opisuje właściwości punktu końcowego usługi Azure SignalR Service.
Możesz skonfigurować wiele punktów końcowych wystąpienia podczas korzystania z zestawu SDK usługi Azure SignalR Service za pomocą:
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>"),
}
});
Dostosowywanie routera
Jedyną różnicą między ASP.NET SignalR i ASP.NET Core SignalR jest typ kontekstu http dla .GetNegotiateEndpoint
W przypadku ASP.NET SignalR jest to typ IOwinContext .
Poniższy kod jest niestandardowym przykładem negocjowania dla usługi 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
}
}
Nie zapomnij zarejestrować routera w kontenerze DI przy użyciu:
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>")
};
});
Metryki punktu końcowego usługi
Aby włączyć zaawansowany router, zestaw SDK serwera SignalR udostępnia wiele metryk, które ułatwiają serwerowi podejmowanie inteligentnych decyzji. Właściwości znajdują się w obszarze ServiceEndpoint.EndpointMetrics
.
Nazwa metryki | opis |
---|---|
ClientConnectionCount |
Łączna liczba współbieżnych połączeń klienckich we wszystkich centrach punktu końcowego usługi |
ServerConnectionCount |
Łączna liczba współbieżnych połączeń serwera we wszystkich centrach punktu końcowego usługi |
ConnectionCapacity |
Łączny limit przydziału połączeń dla punktu końcowego usługi, w tym połączenia klienta i serwera |
Poniższy kod jest przykładem dostosowywania routera zgodnie z 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
}
}
Punkty usługi skalowania dynamicznego
Z zestawu SDK w wersji 1.5.0 włączamy dynamiczne skalowanie punktów serviceEndpoint dla wersji ASP.NET Core. Dlatego nie musisz ponownie uruchamiać serwera aplikacji, gdy trzeba dodać/usunąć punkt końcowy usługi. Ponieważ platforma ASP.NET Core obsługuje konfigurację domyślną, na przykład appsettings.json
w programie reloadOnChange: true
, nie musisz zmieniać kodu i jest ona obsługiwana z natury. Jeśli chcesz dodać niestandardową konfigurację i pracować z przeładowywaniem na gorąco, zapoznaj się z tematem Konfiguracja w programie ASP.NET Core.
Uwaga
Biorąc pod uwagę czas konfigurowania połączenia między serwerem/usługą i klientem/usługą, może być inny, aby zapewnić brak utraty komunikatów podczas procesu skalowania, mamy okres przejściowy oczekiwania na przygotowanie połączeń serwera przed otwarciem nowego punktu usługi ServiceEndpoint dla klientów. Zazwyczaj ukończenie tego procesu trwa kilka sekund i będzie można zobaczyć komunikat dziennika, na przykład Succeed in adding endpoint: '{endpoint}'
wskazujący ukończenie procesu.
W niektórych oczekiwanych sytuacjach, takich jak problemy z siecią między regionami lub niespójności konfiguracji na różnych serwerach aplikacji, okres przejściowy może nie zakończyć się poprawnie. W takich przypadkach zaleca się ponowne uruchomienie serwera aplikacji, gdy proces skalowania nie działa poprawnie.
Domyślny okres limitu czasu dla skali wynosi 5 minut i można go dostosować, zmieniając wartość w pliku ServiceOptions.ServiceScaleTimeout
. Jeśli masz wiele serwerów aplikacji, zaleca się rozszerzenie wartości nieco więcej.
Uwaga
Obecnie funkcja wielu punktów końcowych jest obsługiwana tylko w Persistent
przypadku typu transportu.
W przypadku rozszerzeń usługi SignalR Functions
Konfigurowanie
Aby włączyć wiele wystąpień usługi SignalR Service, należy:
Użyj
Persistent
typu transportu.Domyślny typ transportu to
Transient
tryb. Do pliku lub ustawienia aplikacji na platformie Azure należy dodać następujący wpislocal.settings.json
.{ "AzureSignalRServiceTransportType":"Persistent" }
Uwaga
Podczas przełączania z
Transient
trybu naPersistent
tryb może wystąpić zmiana zachowania serializacji JSON, ponieważ wTransient
trybie biblioteka jest używana do serializacji argumentów metod centrum, jednak wPersistent
trybieNewtonsoft.Json
System.Text.Json
biblioteka jest używana jako domyślna.System.Text.Json
ma pewne kluczowe różnice w zachowaniu domyślnym za pomocą poleceniaNewtonsoft.Json
. Jeśli chcesz użyćNewtonsoft.Json
Persistent
trybu, możesz dodać element konfiguracji:"Azure:SignalR:HubProtocol":"NewtonsoftJson"
w pliku lubAzure__SignalR__HubProtocol=NewtonsoftJson
wlocal.settings.json
witrynie Azure Portal.Skonfiguruj wiele wpisów punktów końcowych usługi SignalR Service w konfiguracji.
Używamy
ServiceEndpoint
obiektu do reprezentowania wystąpienia usługi SignalR Service. Punkt końcowy usługi można zdefiniować przy użyciu jego<EndpointName>
i<EndpointType>
w kluczu wejściowym, a parametry połączenia w wartości wpisu. Klucze mają następujący format:Azure:SignalR:Endpoints:<EndpointName>:<EndpointType>
<EndpointType>
parametr jest opcjonalny i domyślnie ma wartośćprimary
. Zobacz przykłady poniżej:{ "Azure:SignalR:Endpoints:EastUs":"<ConnectionString>", "Azure:SignalR:Endpoints:EastUs2:Secondary":"<ConnectionString>", "Azure:SignalR:Endpoints:WestUs:Primary":"<ConnectionString>" }
Uwaga
Podczas konfigurowania punktów końcowych usługi Azure SignalR w usłudze App Service w witrynie Azure Portal nie zapomnij zastąpić
":"
wartością"__"
, podwójne podkreślenie w kluczach. Ze względów zobacz Zmienne środowiskowe.Parametry połączenia skonfigurowane przy użyciu klucza
{ConnectionStringSetting}
(domyślnie "AzureSignalRConnectionString") są również rozpoznawane jako podstawowy punkt końcowy usługi o pustej nazwie. Jednak ten styl konfiguracji nie jest zalecany w przypadku wielu punktów końcowych.
Routing
Zachowanie domyślne
Domyślnie powiązanie funkcji używa elementu DefaultEndpointRouter do pobrania punktów końcowych.
Routing klienta: losowo wybierz jeden punkt końcowy z podstawowych punktów końcowych online . Jeśli wszystkie podstawowe punkty końcowe są w trybie offline, losowo wybierz jeden pomocniczy punkt końcowy online . Jeśli zaznaczenie nie powiedzie się ponownie, zostanie zgłoszony wyjątek.
Routing komunikatów serwera: zwracane są wszystkie punkty końcowe usługi.
Dostosowanie
Model in-process języka C#
Oto konkretne kroki:
Zaimplementuj dostosowany router. Możesz skorzystać z informacji dostarczonych z
ServiceEndpoint
programu , aby podjąć decyzję o routingu. Zobacz przewodnik tutaj: customize-route-algorithm. Należy pamiętać, że wyzwalacz HTTP jest wymagany w funkcji negocjacji, gdy potrzebujeszHttpContext
niestandardowej metody negocjacji.Zarejestruj router w kontenerze 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>();
}
}
}
Model procesów izolowanych
W przypadku funkcji działających w modelu izolowanego procesu obsługujemy określanie docelowych punktów końcowych w każdym żądaniu. Nowe typy powiązań będą używane do uzyskiwania informacji o punkcie końcowym.
Rozsyłanie po stronie klienta
Powiązanie SignalRConnectionInfo
wybiera jeden punkt końcowy zgodnie z domyślną regułą routingu. Jeśli chcesz dostosować regułę routingu, należy użyć SignalRNegotiation
powiązania zamiast SignalRConnectionInfo
powiązania.
SignalRNegotiation
właściwości konfiguracji powiązania są takie same jak SignalRConnectionInfo
. function.json
Oto przykładowy plik:
{
"type": "signalRNegotiation",
"name": "negotiationContext",
"hubName": "<HubName>",
"direction": "in"
}
Możesz również dodać inne dane powiązania, takie jak userId
, idToken
i claimTypeList
tak jak SignalRConnectionInfo
.
Obiekt uzyskany z SignalRNegotiation
powiązania ma następujący format:
{
"endpoints": [
{
"endpointType": "Primary",
"name": "<EndpointName>",
"endpoint": "https://****.service.signalr.net",
"online": true,
"connectionInfo": {
"url": "<client-access-url>",
"accessToken": "<client-access-token>"
}
},
{
"...": "..."
}
]
}
Oto przykład SignalRNegotiation
użycia języka JavaScript powiązania:
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;
}
}
Routing komunikatów
Routing komunikatów lub akcji wymaga dwóch typów powiązań do współpracy. Ogólnie rzecz biorąc, najpierw potrzebujesz nowego typu SignalREndpoints
powiązania wejściowego, aby uzyskać wszystkie dostępne informacje o punkcie końcowym. Następnie przefiltrujesz punkty końcowe i uzyskasz tablicę zawierającą wszystkie punkty końcowe, do których chcesz wysłać. Na koniec należy określić docelowe punkty końcowe w powiązaniu wyjściowym SignalR
.
SignalREndpoints
Oto właściwości konfiguracji powiązania w functions.json
pliku:
{
"type": "signalREndpoints",
"direction": "in",
"name": "endpoints",
"hubName": "<HubName>"
}
Obiekt uzyskany z SignalREndpoints
programu to tablica punktów końcowych, z których każdy jest reprezentowany jako obiekt JSON z następującym schematem:
{
"endpointType": "<EndpointType>",
"name": "<EndpointName>",
"endpoint": "https://****.service.signalr.net",
"online": true
}
Po pobraniu docelowej tablicy punktów końcowych dodaj endpoints
właściwość do obiektu powiązania wyjściowego. Jest to przykład w języku 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();
}
Dla zestawu SDK zarządzania
Dodawanie wielu punktów końcowych z konfiguracji
Skonfiguruj przy użyciu klucza Azure:SignalR:Endpoints
dla parametry połączenia usługi SignalR Service. Klucz powinien być w formacie Azure:SignalR:Endpoints:{Name}:{EndpointType}
, gdzie Name
i EndpointType
są właściwościami ServiceEndpoint
obiektu i są dostępne z kodu.
Możesz dodać wiele parametry połączenia wystąpień przy użyciu następujących dotnet
poleceń:
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>
Dodawanie wielu punktów końcowych z kodu
Klasa ServiceEndpoint
opisuje właściwości punktu końcowego usługi Azure SignalR Service.
Możesz skonfigurować wiele punktów końcowych wystąpienia podczas korzystania z zestawu Azure SignalR Management SDK za pośrednictwem:
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();
Dostosowywanie routera punktu końcowego
Domyślnie zestaw SDK używa elementu DefaultEndpointRouter do odbierania punktów końcowych.
Zachowanie domyślne
Routing żądań klienta:
Gdy klient
/negotiate
z serwerem aplikacji. Domyślnie zestaw SDK losowo wybiera jeden punkt końcowy z zestawu dostępnych punktów końcowych usługi.Routing komunikatów serwera:
Podczas wysyłania komunikatu do określonego połączenia , a połączenie docelowe jest kierowane do bieżącego serwera, komunikat przechodzi bezpośrednio do tego połączonego punktu końcowego. W przeciwnym razie komunikaty są emitowane do każdego punktu końcowego usługi Azure SignalR.
Dostosowywanie algorytmu routingu
Możesz utworzyć własny router, gdy masz specjalną wiedzę, aby określić, do których punktów końcowych powinny przejść komunikaty.
W poniższym przykładzie zdefiniowano router niestandardowy, który kieruje komunikaty grupą rozpoczynającą east-
się od punktu końcowego o nazwie 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);
}
}
Poniższy przykład zastępuje domyślne zachowanie negocjowania i wybiera punkt końcowy w zależności od lokalizacji serwera aplikacji.
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
}
}
Nie zapomnij zarejestrować routera w kontenerze DI przy użyciu:
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();
Konfiguracja w scenariuszach obejmujących wiele regionów
Obiekt ServiceEndpoint
ma EndpointType
właściwość o wartości primary
lub secondary
.
Podstawowe punkty końcowe są preferowanymi punktami końcowymi do odbierania ruchu klienta, ponieważ mają bardziej niezawodne połączenia sieciowe. Pomocnicze punkty końcowe mają mniej niezawodne połączenia sieciowe i są używane tylko dla serwera do ruchu klienta. Na przykład pomocnicze punkty końcowe są używane do nadawania komunikatów zamiast klienta do ruchu serwera.
W przypadkach obejmujących wiele regionów sieć może być niestabilna. W przypadku serwera aplikacji znajdującego się w regionie Wschodnie stany USA punkt końcowy usługi SignalR Service znajdujący się w tym samym regionie Wschodnie stany USA to primary
i punkty końcowe w innych regionach oznaczonych jako secondary
. W tej konfiguracji punkty końcowe usługi w innych regionach mogą odbierać komunikaty z tego serwera aplikacji Wschodnie stany USA, ale do tego serwera aplikacji nie są kierowani klienci między regionami. Na poniższym diagramie przedstawiono architekturę:
Gdy klient spróbuje /negotiate
z serwerem aplikacji z routerem domyślnym, zestaw SDK losowo wybiera jeden punkt końcowy z zestawu dostępnych primary
punktów końcowych. Gdy podstawowy punkt końcowy jest niedostępny, zestaw SDK wybiera losowo wszystkie dostępne secondary
punkty końcowe. Punkt końcowy jest oznaczony jako dostępny , gdy połączenie między serwerem a punktem końcowym usługi jest aktywne.
W scenariuszu między regionami, gdy klient spróbuje /negotiate
z serwerem aplikacji hostowanym w regionie Wschodnie stany USA, domyślnie zawsze zwraca primary
punkt końcowy znajdujący się w tym samym regionie. Gdy wszystkie punkty końcowe Wschodnie stany USA nie są dostępne, router przekierowuje klienta do punktów końcowych w innych regionach. W poniższej sekcji trybu failover opisano szczegółowo scenariusz.
Tryb failover
Gdy punkt końcowy nie primary
jest dostępny, klient /negotiate
wybiera z dostępnych secondary
punktów końcowych. Ten mechanizm trybu failover wymaga, aby każdy punkt końcowy był primary
punktem końcowym co najmniej jednego serwera aplikacji.
Następne kroki
W scenariuszach wysokiej dostępności i odzyskiwania po awarii można używać wielu punktów końcowych.