Общие сведения о масштабировании в SignalR
Предупреждение
Эта документация не подходит для последней версии SignalR. Ознакомьтесь с ASP.NET Core SignalR.
Версии программного обеспечения, используемые в этом разделе
- Visual Studio 2013
- .NET 4.5
- SignalR версии 2
Предыдущие версии этого раздела
Сведения о более ранних версиях SignalR см. в разделе Старые версии SignalR.
Вопросы и комментарии
Оставьте отзыв о том, как вам понравилось это руководство и что мы могли бы улучшить в комментариях в нижней части страницы. Если у вас есть вопросы, которые не связаны непосредственно с руководством, вы можете опубликовать их на форуме ASP.NET SignalR или StackOverflow.com.
Как правило, существует два способа масштабирования веб-приложения: вертикальное и горизонтальное масштабирование.
- Увеличение масштаба означает использование сервера большего размера (или более крупной виртуальной машины) с большим объемом ОЗУ, ЦП и т. д.
- Горизонтальное масштабирование означает добавление дополнительных серверов для обработки нагрузки.
Проблема с увеличением масштаба заключается в том, что вы быстро достигли ограничения на размер машины. Кроме того, вам нужно масштабировать. Однако при горизонтальном масштабировании клиенты могут направляться на разные серверы. Клиент, подключенный к одному серверу, не будет получать сообщения, отправленные с другого сервера.
Одним из решений является пересылка сообщений между серверами с помощью компонента, который называется объединителе. При включенной объединителю каждый экземпляр приложения отправляет сообщения обратной панели, а объединителю перенаправит их другим экземплярам приложения. (В электронике задняя плоскость представляет собой группу параллельных соединителей. По аналогии обратная плоскость SignalR подключает несколько серверов.)
В настоящее время SignalR предоставляет три обратные плоскости:
- Служебная шина Azure. Служебная шина — это инфраструктура обмена сообщениями, которая позволяет компонентам отправлять сообщения слабосвязанным способом.
- Редис. Redis — это хранилище ключей и значений в памяти. Redis поддерживает шаблон публикации и подписки ("публикация/подписка") для отправки сообщений.
- SQL Server. Объединитедняя панель SQL Server записывает сообщения в таблицы SQL. Для эффективного обмена сообщениями в объединителе используется Компонент Service Broker. Однако он также работает, если компонент Service Broker не включен.
Если вы развертываете приложение в Azure, рассмотрите возможность использования серверной панели Redis с помощью кэша Redis для Azure. При развертывании в собственной ферме серверов рассмотрите SQL Server или объединитее платы Redis.
В следующих разделах содержатся пошаговые руководства по каждой объединителе.
- Масштабирование SignalR с помощью служебной шины Azure
- Масштабирование SignalR с помощью Redis
- Масштабирование SignalR с помощью SQL Server
Реализация
В SignalR каждое сообщение отправляется через шину сообщений. Шина сообщений реализует интерфейс IMessageBus , который предоставляет абстракцию публикации и подписки. Для работы объединителенных плоскостей вместо IMessageBus по умолчанию используется шина, предназначенная для этой задней панели. Например, шиной сообщений для Redis является RedisMessageBus, и она использует механизм публикации и подсети Redis для отправки и получения сообщений.
Каждый экземпляр сервера подключается к задней плате через шину. При отправке сообщения оно передается на объединителю, а объединителю отправляет его на каждый сервер. Когда сервер получает сообщение из задней панели, он помещает сообщение в свой локальный кэш. Затем сервер доставляет сообщения клиентам из локального кэша.
Для каждого клиентского подключения ход чтения потока сообщений отслеживается с помощью курсора. (Курсор представляет позицию в потоке сообщений.) Если клиент отключается, а затем повторно подключается, он запрашивает у шины все сообщения, поступающие после значения курсора клиента. То же самое происходит, когда соединение использует длительный опрос. После завершения длительного запроса на опрос клиент открывает новое подключение и запрашивает сообщения, поступающие после курсора.
Механизм курсора работает, даже если при повторном подключении клиент направляется на другой сервер. Объединитеьная панель знает обо всех серверах, и не имеет значения, к какому серверу подключается клиент.
Ограничения
При использовании объединитерной платы максимальная пропускная способность сообщений ниже, чем при непосредственном подключении клиентов к одному узлу сервера. Это связано с тем, что объединительная панель перенаправит каждое сообщение на каждый узел, поэтому объединительная панель может стать узким местом. Является ли это ограничение проблемой, зависит от приложения. Например, ниже приведены некоторые типичные сценарии SignalR.
- Широковещательная трансляция сервера (например, stock ticker). В этом сценарии хорошо работают обратные платы, так как сервер управляет скоростью отправки сообщений.
- Клиент-клиент (например, чат). В этом сценарии объединительная панель может быть узким местом, если количество сообщений масштабируется с количеством клиентов; то есть, если скорость сообщений увеличивается пропорционально по мере присоединения большего числа клиентов.
- Высокочастотный режим реального времени (например, игры в режиме реального времени). В этом сценарии не рекомендуется использовать обратную плоскость.
Включение трассировки для масштабирования Signalr
Чтобы включить трассировку для объединителю, добавьте следующие разделы в файл web.config в корневом элементе конфигурации :
<configuration>
<system.diagnostics>
<sources>
<source name="SignalR.SqlMessageBus">
<listeners>
<add name="SignalR-Bus" />
</listeners>
</source>
<source name="SignalR.ServiceBusMessageBus">
<listeners>
<add name="SignalR-Bus" />
</listeners>
</source>
<source name="SignalR.ScaleoutMessageBus">
<listeners>
<add name="SignalR-Bus" />
</listeners>
</source>
</sources>
<switches>
<add name="SignalRSwitch" value="Verbose" />
<!-- Off, Critical, Error, Warning, Information, Verbose -->
</switches>
<sharedListeners>
<add name="SignalR-Bus"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="bus.log.txt" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
. . .
</configuration>