Azure SignalR и веб-приложение Azure с несколькими экземплярами

Мы разрабатываем ядро ​​ASP.Net, которое размещается как веб-приложение Azure.

Мы также используем сервис Azure SignalR

Все прекрасно работает, пока у нас есть один экземпляр Web-приложения, но как только мы его масштабируем, у нас возникает следующая проблема:

  1. От действия Контроллера мы разрешаем IHubContext и отправляем сообщение клиенту Hub. Пока все отлично работает
  2. Клиент 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 решения, которые я мог бы предложить для этого сценария

  1. @LexLi предложил хороший подход для решения этой проблемы. Таким образом, вы можете сделать свое веб-приложение клиентом SignalR и сделать его членом группы. Таким образом, каждый экземпляр веб-приложения также является клиентом, и затем экземпляр, который получает ответ для клиента Hub, может передать этот ответ группе экземпляров веб-приложения.

  2. Вы можете использовать темы Azure Service Bus. Так что после запуска экземпляр начнет подписываться на прослушивание темы. И затем, когда любой экземпляр получает ответ от клиента-концентратора, он помещает ответ в раздел служебной шины, а затем каждый экземпляр получает этот ответ от темы.

Я надеялся, что может быть лучшее решение для такой проблемы

Другие вопросы по тегам