- PVSM.RU - https://www.pvsm.ru -
SignalR появился достаточно давно, года 3 назад были первые версии и нужен он для создания Real-time веб приложений. Во всех блогах показывали “hello word” с чатом, в одно серверной конфигурации, но никто не рассказывал о приложениях из реального мира.
В реальном/взрослом мире веб сервер не работает в одиночку, всегда работает пусть и маленькая, но ферма веб серверов, стоящих за балансировщиком. Следовательно, SignalR должен быть распределенным и событие, возникающее на одном из серверов, приходило и клиентам подключенным к другому. Поскольку о том, что SignalR поддерживает такую возможность не заслуженно не писалось, я хочу исправить это.
В SignalR есть такая фича — backplane, и представляет она из себя сервер баз данных (либо Redis, либо MSSQL Server и для Azure есть ServiceBus. Других официальных нет). На одном из хостов SignalR происходит событие, оно отправляется в базу, а оттуда уже рассылается всем подключенным к нему остальным хостам SignalR, которые ретранслируют это сообщения своим клиентам.
BackPlane в электронике- группа параллельных транзисторов.
В случаи использования Redis используется нативный для него механизм [1] Pub/Sub [2], появившийся с версии Redis 2.8 (хотя и еще с версии 2.0 была возможность работать с каналами и публиковать в них сообщения).
В случаи SQL Server есть 2 варианта: с использованием Service Broker (это быстрый способ поддержки обмена сообщениями) и без его использования.
Конфигурирование во всех 3 случаях одинаковое и достаточно простое.
Именно поэтому я бы рекомендовал использовать это решение, а не тратить человеко-месяцы старших разработчиков на написание собственных велосипедов с не гарантированным результатом.
Чтобы все работало, мы должны реализовать класс, который имплементирует интерфейс IMessageBus [3].
В нем всего 2 метода:
Клиент к Redis/SQLServer реализует этот интерфейс через наследование от ScaleOutMessageBus, который в свою очередь наследуется от MessageBus, который уже имплементирует IMessageBus. Если захотим написать сами с нуля, то можно всю эту иерархию наследования пропустить. RedisMassageBus [4] описание.
На github есть вот такой [5] проект, в котором есть код для backplane использующий SQL Server.
Операция Send выполнена как просто вставка в базу данных через SQLCommand.
Получение обновлений проходит через класс SQLStream (Кто знаком с концепциями реактивного программирования узнают код.), где SQLReciever подписывается на обновления в базе.
Для получения обновлений используется SqlDependency [6]. Текст sql команд жестко забит в код и как только происходит изменения таблицы в бд, signalr получит уведомление об этом.
В этом же проекте можно посмотреть, как происходит инициализация базы… Происходит оно через класс SqlInstaller.cs, который читает файл install.sql, через string.replace подменяет значения параметров (имя схемы и еще несколько параметров), затем выполняя скрипт через обычный ado.net sqlcommand.
Одним словом- ракетными технологиями и не пахло.
В случаи Redis, клиент подписывается на канал и ожидает ответа. Исходного кода nuget пакета на github я не нашел, а декомпилировать не вижу смысла и сейчас объясню почему.
Есть зависимость на nuget, и без декомпиляции можно сказать, что для работы с Redis используется библиотека [7]. Эта библиотека устарела, и надо использовать StackExchange.Redis как и в остальных проектах команды Asp.net (EntityFramework, кэширование, сессии). По этому поводу даже задачка [8] у команды SignalR есть и в версии 2.2. команда SignalR обещает переписать. Если будут переписывать, то и смотреть сейчас смысла особого нет. Текущая версия 2.1.2 от сентября 2014 года.
Я думаю ни для кого не станет открытием, что использование BackPlane снизит производительность на каждую конкретную ноду кластера (т.к. идет отправка данных на базу данных), и увеличит трафик между серверами т.к. сообщения полетят от базы данных ко всем нодами. Но это та цена, которую надо заплатить для если мы хотим получить горизонтальное масштабирование. Точный процент ни в статьях не указан, ни у меня посчитать не получилось. Все зависит от вашей конфигурации железа, топологии и т.п.
Я провел эксперимент. В моем эксперименте я использовал свой ноуткбук с 2 инстансами приложения типа чата, на asp.net5 + Redis. В своих замерах я ничего интересного не смог показать, т.к. SignalR собирает несколько сообщений в пакет и после какой-то частоты замерить время отправки сообщения уже невозможно. Ну и сам net не обеспечивает сильно высокую точность замера времени, чтобы что-то меньше чем 50мс замерить.
Сами Microsoft говорят о 2 потенциальных сценариях, когда backplane может быть не очень хорошо.
В остальных случаях, BackPlane использовать можно, и он дает возможность использовать кластер веб серверов с SignalR.
Ссылки
Автор: SychevIgor
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/net/78330
Ссылки в тексте:
[1] механизм: http://redis.io/topics/pubsub
[2] Pub/Sub: http://redis.io/commands/pubsub
[3] IMessageBus: http://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.messaging.IMessageBus(v=vs.100).aspx
[4] RedisMassageBus: http://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.redis.redismessagebus(v=vs.100).aspx
[5] такой: https://github.com/aspnet/SignalR-SqlServer
[6] SqlDependency: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldependency(v=vs.110).aspx
[7] библиотека: http://www.nuget.org/packages/BookSleeve/
[8] задачка: https://github.com/SignalR/SignalR/issues/2961
[9] www.asp.net/signalr/overview/performance/scaleout-in-signalr: http://www.asp.net/signalr/overview/performance/scaleout-in-signalr
[10] www.asp.net/signalr/overview/performance/scaleout-with-sql-server: http://www.asp.net/signalr/overview/performance/scaleout-with-sql-server
[11] www.asp.net/signalr/overview/performance/scaleout-with-redis: http://www.asp.net/signalr/overview/performance/scaleout-with-redis
[12] www.nuget.org/packages/Microsoft.AspNet.SignalR.Redis: https://www.nuget.org/packages/Microsoft.AspNet.SignalR.Redis
[13] www.nuget.org/packages/Microsoft.AspNet.SignalR.SqlServer: https://www.nuget.org/packages/Microsoft.AspNet.SignalR.SqlServer
[14] Источник: http://habrahabr.ru/post/108929/
Нажмите здесь для печати.