Azure SignalR и веб-приложение Azure с несколькими экземплярами
Мы разрабатываем ядро ASP.Net, которое размещается как веб-приложение Azure.
Мы также используем сервис Azure SignalR
Все прекрасно работает, пока у нас есть один экземпляр Web-приложения, но как только мы его масштабируем, у нас возникает следующая проблема:
- От действия Контроллера мы разрешаем IHubContext и отправляем сообщение клиенту Hub. Пока все отлично работает
- Клиент Hub принимает ответ и отправляет его конечной точке TheHub.
Проблема в том, что ответ может быть отправлен в другой экземпляр Web App. Таким образом, мы отправляем запрос от экземпляра № 1, но ответ отправляется на экземпляр № 2 с вероятностью 50%, а экземпляр № 1 никогда не получает ответ
Любые идеи о том, как мы могли бы сделать так, чтобы отправленный запрос действительно получил ответ?
3 ответа
SignalR имеет готовую поддержку сценариев масштабирования, это называется объединительными платами. Идея заключается в том, что с помощью одного из компонентов объединительной платы события SignalR будут распространяться по всем экземплярам. Для фреймворка Asp.Net используйте один из этих пакетов
Microsoft.AspNet.SignalR.ServiceBus3
Microsoft.AspNet.SignalR.ServiceBus
Microsoft.AspNet.SignalR.StackExchangeRedis
Microsoft.AspNet.SignalR.SqlServer
Для ASP.Net Core только Redis портируется с Microsoft.AspNetCore.SignalR.StackExchangeRedis
пакет, но некоторые из них предоставляются сообществом, см. https://github.com/thomaslevesque/AspNetCore.SignalR.AzureServiceBus
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR()
.AddAzureSignalR(options =>
{
options.ApplicationName = "app1";
}
);
}
Вы можете указать ApplicationName в SDK сервера для разных групп серверов.
Это поможет вашему серверу генерировать токены доступа, такие как ......?hub=app1_<your_hub>, во время согласования, которые могут помочь нашим экземплярам ASRS различать соединения, поступающие из разных групп серверов.
К сожалению, я не нашел надежного решения, которое не потребовало бы немного неуклюжих обходных путей
Но есть 2 решения, которые я мог бы предложить для этого сценария
@LexLi предложил хороший подход для решения этой проблемы. Таким образом, вы можете сделать свое веб-приложение клиентом SignalR и сделать его членом группы. Таким образом, каждый экземпляр веб-приложения также является клиентом, и затем экземпляр, который получает ответ для клиента Hub, может передать этот ответ группе экземпляров веб-приложения.
Вы можете использовать темы Azure Service Bus. Так что после запуска экземпляр начнет подписываться на прослушивание темы. И затем, когда любой экземпляр получает ответ от клиента-концентратора, он помещает ответ в раздел служебной шины, а затем каждый экземпляр получает этот ответ от темы.
Я надеялся, что может быть лучшее решение для такой проблемы