Масштабирование Служба SignalR с несколькими экземплярами
пакет SDK Служба SignalR поддерживает несколько конечных точек для Служба SignalR экземпляров. Эту функцию можно использовать для масштабирования одновременных подключений или для обмена сообщениями между регионами.
Для ASP.NET Core
Добавление нескольких конечных точек из конфигурации
Настройте ключ Azure:SignalR:ConnectionString
или Azure:SignalR:ConnectionString:
для Служба SignalR строка подключения.
Если ключ начинается с Azure:SignalR:ConnectionString:
, он должен находиться в формате Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, где Name
и EndpointType
являются свойствами ServiceEndpoint
объекта и доступны из кода.
С помощью следующих команд dotnet
можно добавить несколько строк подключения экземпляра.
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>
Добавление нескольких конечных точек из кода
Класс ServiceEndpoint
описывает свойства конечной точки Служба Azure SignalR.
При использовании пакета SDK для службы Azure SignalR можно настроить несколько конечных точек экземпляра с помощью следующего.
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"),
};
});
Настройка маршрутизатора конечной точки
По умолчанию пакет SDK использует DefaultEndpointRouter для выбора конечных точек.
Поведение по умолчанию
Маршрутизация запросов клиента:
Когда клиент
/negotiate
с сервером приложений. По умолчанию пакет SDK случайным образом выбирает одну конечную точку из набора доступных конечных точек службы.Маршрутизация сообщений сервера:
При отправке сообщения в определенное подключение и целевое подключение направляется на текущий сервер, сообщение передается непосредственно в подключенную конечную точку. В противном случае сообщения будут транслироваться в каждую конечную точку Azure SignalR.
Настройка алгоритма маршрутизации
Вы можете создать собственный маршрутизатор, если вы обладаете специальными знаниями для определения конечных точек, на которые должны отправляться сообщения.
В следующем примере определяется пользовательский маршрутизатор, который направляет сообщения с группой, начиная с east-
конечной точки с именем 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);
}
}
Следующий пример переопределяет поведение согласования по умолчанию и выбирает конечную точку в зависимости от расположения сервера приложений.
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
}
}
Обязательно зарегистрируйте маршрутизатор в контейнере DI с помощью следующего.
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>")
};
});
Для ASP.NET
Добавление нескольких конечных точек из конфигурации
Конфигурация с ключом Azure:SignalR:ConnectionString
или Azure:SignalR:ConnectionString:
для Служба SignalR строка подключения.
Если ключ начинается с Azure:SignalR:ConnectionString:
, он должен иметь формат Azure:SignalR:ConnectionString:{Name}:{EndpointType}
, где Name
и EndpointType
являются свойствами объекта ServiceEndpoint
и доступны из кода.
В 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>
Добавление нескольких конечных точек из кода
Класс ServiceEndpoint
описывает свойства конечной точки Служба Azure SignalR.
При использовании пакета SDK для службы Azure SignalR можно настроить несколько конечных точек экземпляра с помощью следующего.
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>"),
}
});
Настройка маршрутизатора
Единственное различие между ASP.NET SignalR и ASP.NET Core SignalR — это тип контекста HTTP для GetNegotiateEndpoint
. Для ASP.NET SignalR его тип IOwinContext.
Следующий код — это пользовательский пример согласования для 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
}
}
Обязательно зарегистрируйте маршрутизатор в контейнере DI с помощью следующего.
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>")
};
});
Метрики конечных точек службы
Чтобы включить расширенный маршрутизатор, пакет SDK сервера SignalR предоставляет несколько метрик, помогая серверу принимать интеллектуальные решения. Свойства находятся в разделе ServiceEndpoint.EndpointMetrics
.
Имя метрики | Description |
---|---|
ClientConnectionCount |
Общее количество одновременных клиентских подключений ко всем центрам для конечной точки службы |
ServerConnectionCount |
Общее количество одновременных подключений к серверу во всех центрах для конечной точки службы |
ConnectionCapacity |
Общая квота подключения для конечной точки службы, включая подключения клиента и сервера |
Следующий код является примером настройки маршрутизатора в соответствии с 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
}
}
Динамические масштабируемые службыEndpoints
В пакете SDK версии 1.5.0 сначала мы включаем динамические масштабируемые службы ServiceEndpoints для ASP.NET core версии. Поэтому вам не нужно перезапустить сервер приложений, если необходимо добавить или удалить ServiceEndpoint. Так как ASP.NET Core поддерживает конфигурацию по умолчанию, как appsettings.json
и с reloadOnChange: true
, вам не нужно изменять код, и она поддерживается по природе. Если вы хотите добавить настраиваемую конфигурацию и работать с горячей перезагрузкой, см. раздел "Конфигурация" в ASP.NET Core.
Примечание.
Учитывая, что время настройки подключения между сервером или службой и клиентом или службой может отличаться, чтобы не было потери сообщений во время процесса масштабирования, у нас есть промежуточный период ожидания готовности подключений к серверу перед открытием нового ServiceEndpoint для клиентов. Обычно требуется несколько секунд, и вы сможете увидеть сообщение журнала, например Succeed in adding endpoint: '{endpoint}'
, которое указывает на завершение процесса.
В некоторых ожидаемых ситуациях, таких как проблемы с сетью между регионами или несоответствия конфигурации на разных серверах приложений, промежуточный период может завершиться неправильно. В таких случаях рекомендуется перезапустить сервер приложений, когда процесс масштабирования не работает правильно.
Период времени ожидания по умолчанию для шкалы составляет 5 минут, и его можно настроить, изменив значение в ServiceOptions.ServiceScaleTimeout
. Если у вас много серверов приложений, рекомендуется расширить значение немного больше.
Настройка в сценариях с разными регионами
Объект ServiceEndpoint
имеет свойство EndpointType
со значением primary
или secondary
.
Первичные конечные точки предпочтительнее конечных точек для получения клиентского трафика, так как у них есть более надежные сетевые подключения. Вторичные конечные точки имеют менее надежные сетевые подключения и используются только для сервера к клиентскому трафику. Например, вторичные конечные точки используются для трансляции сообщений вместо трафика клиента на сервер.
В разных случаях сеть может быть нестабильной. Для сервера приложений, расположенного в восточной части США, Служба SignalR конечная точка, расположенная в том же регионе Восточная часть США, и primary
конечные точки в других регионах, помеченные как secondary
. В этой конфигурации конечные точки службы в других регионах могут получать сообщения от этого сервера приложений восточной части США , но на этот сервер приложений не направляются клиенты между регионами . На следующей схеме представлена архитектура:
При попытке /negotiate
клиента с сервером приложений с маршрутизатором по умолчанию пакет SDK случайным образом выбирает одну конечную точку из набора доступных primary
конечных точек. Если основная конечная точка недоступна, пакет SDK выбирается случайным образом из всех доступных secondary
конечных точек. Конечная точка помечается как доступная, если подключение между сервером и конечной точкой службы активно.
В сценарии между регионами, когда клиент пытается /negotiate
использовать сервер приложения, размещенный в восточной части США, по умолчанию всегда возвращает primary
конечную точку, расположенную в одном регионе. Если все конечные точки восточной части США недоступны, маршрутизатор перенаправляет клиента на конечные точки в других регионах. В следующем разделе отработки отказа подробно описан сценарий.
Отработка отказа
Если конечная точка недоступна primary
, клиент /negotiate
выбирает из доступных secondary
конечных точек. Этот механизм отработки отказа требует, чтобы каждая конечная точка служила в качестве конечной primary
точки по крайней мере одному серверу приложений.
Следующие шаги
В сценариях высокого уровня доступности и аварийного восстановления можно использовать несколько конечных точек.