...

понедельник, 29 декабря 2014 г.

SignalR в многосерверной конфигурации или по умному — Scaleout

SignalR появился достаточно давно, года 3 назад были первые версии и нужен он для создания Real-time веб приложений. Во всех блогах показывали “hello word” с чатом, в одно серверной конфигурации, но никто не рассказывал о приложениях из реального мира.

В реальном/взрослом мире веб сервер не работает в одиночку, всегда работает пусть и маленькая, но ферма веб серверов, стоящих за балансировщиком. Следовательно, SignalR должен быть распределенным и событие, возникающее на одном из серверов, приходило и клиентам подключенным к другому. Поскольку о том, что SignalR поддерживает такую возможность не заслуженно не писалось, я хочу исправить это.


В SignalR есть такая фича — backplane, и представляет она из себя сервер баз данных (либо Redis, либо MSSQL Server и для Azure есть ServiceBus. Других официальных нет). На одном из хостов SignalR происходит событие, оно отправляется в базу, а оттуда уже рассылается всем подключенным к нему остальным хостам SignalR, которые ретранслируют это сообщения своим клиентам.


image

BackPlane в электронике- группа параллельных транзисторов.


В случаи использования Redis используется нативный для него механизм Pub/Sub, появившийся с версии Redis 2.8 (хотя и еще с версии 2.0 была возможность работать с каналами и публиковать в них сообщения).

image


В случаи SQL Server есть 2 варианта: с использованием Service Broker (это быстрый способ поддержки обмена сообщениями) и без его использования.

image


Конфигурирование



Конфигурирование во всех 3 случаях одинаковое и достаточно простое.

image


Именно поэтому я бы рекомендовал использовать это решение, а не тратить человеко-месяцы старших разработчиков на написание собственных велосипедов с не гарантированным результатом.


Реализация



Чтобы все работало, мы должны реализовать класс, который имплементирует интерфейс IMessageBus.

В нем всего 2 метода:

image


Клиент к Redis/SQLServer реализует этот интерфейс через наследование от ScaleOutMessageBus, который в свою очередь наследуется от MessageBus, который уже имплементирует IMessageBus. Если захотим написать сами с нуля, то можно всю эту иерархию наследования пропустить. RedisMassageBus описание.


SQL Server реализация.



На github есть вот такой проект, в котором есть код для backplane использующий SQL Server.

Внутреннее устройство я расскажу по нему, хотя не до конца уверен, что это именно то, что есть на nuget.
Проект был порядка месяца назад опубликован, а пакеты уже года 2 доступны. Плюс в проекте всего 3 коммита, и 3 ветки, которые слабо объясняют, что в них находится, а главное — в ветке master/dev вообще ничего нет.

image




Операция Send выполнена как просто вставка в базу данных через SQLCommand.

Получение обновлений проходит через класс SQLStream (Кто знаком с концепциями реактивного программирования узнают код.), где SQLReciever подписывается на обновления в базе.

Для получения обновлений используется SqlDependency . Текст sql команд жестко забит в код и как только происходит изменения таблицы в бд, signalr получит уведомление об этом.


В этом же проекте можно посмотреть, как происходит инициализация базы… Происходит оно через класс SqlInstaller.cs, который читает файл install.sql, через string.replace подменяет значения параметров (имя схемы и еще несколько параметров), затем выполняя скрипт через обычный ado.net sqlcommand.


image


Одним словом- ракетными технологиями и не пахло.


Реализация Redis



В случаи Redis, клиент подписывается на канал и ожидает ответа. Исходного кода nuget пакета на github я не нашел, а декомпилировать не вижу смысла и сейчас объясню почему.

Есть зависимость на nuget, и без декомпиляции можно сказать, что для работы с Redis используется библиотека. Эта библиотека устарела, и надо использовать StackExchange.Redis как и в остальных проектах команды Asp.net (EntityFramework, кэширование, сессии). По этому поводу даже задачка у команды SignalR есть и в версии 2.2. команда SignalR обещает переписать. Если будут переписывать, то и смотреть сейчас смысла особого нет. Текущая версия 2.1.2 от сентября 2014 года.
Производительность



Я думаю ни для кого не станет открытием, что использование BackPlane снизит производительность на каждую конкретную ноду кластера (т.к. идет отправка данных на базу данных), и увеличит трафик между серверами т.к. сообщения полетят от базы данных ко всем нодами. Но это та цена, которую надо заплатить для если мы хотим получить горизонтальное масштабирование. Точный процент ни в статьях не указан, ни у меня посчитать не получилось. Все зависит от вашей конфигурации железа, топологии и т.п.

Я провел эксперимент. В моем эксперименте я использовал свой ноуткбук с 2 инстансами приложения типа чата, на asp.net5 + Redis. В своих замерах я ничего интересного не смог показать, т.к. SignalR собирает несколько сообщений в пакет и после какой-то частоты замерить время отправки сообщения уже невозможно. Ну и сам net не обеспечивает сильно высокую точность замера времени, чтобы что-то меньше чем 50мс замерить.


Сами Microsoft говорят о 2 потенциальных сценариях, когда backplane может быть не очень хорошо.



  • Когда очень много серверов связанные через backplane. Т.к. слишком много получается трафика между базой и серверами, с каждым новым сервером объем трафика растет квадратично…

  • Для приложений, которым нужна минимальная задержка прихода сообщений backplane внесет дополнительную задержку (latency растет).


В остальных случаях, BackPlane использовать можно, и он дает возможность использовать кластер веб серверов с SignalR.


Ссылки


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://fivefilters.org/content-only/faq.php#publishers.


Комментариев нет:

Отправить комментарий