Redis backplane
Когда за балансировщиком нагрузки работает несколько экземпляров сервера, рассылка,
опубликованная на одном экземпляре, должна дойти до клиентов, подключённых к остальным.
DarkWS.Redis распространяет рассылки через Redis Pub/Sub.
dotnet add package DarkWS.Redis --version 4.0.0
Зарегистрируйте IConnectionMultiplexer, затем после AddDarkWs добавьте Redis с явным
именем канала:
using DarkWS.Redis;
using StackExchange.Redis;
var redis = await ConnectionMultiplexer.ConnectAsync(builder.Configuration["Redis"]!);
builder.Services.AddSingleton<IConnectionMultiplexer>(redis);
builder.Services
.AddDarkWs()
.AddHandlersFromAssemblyContaining<Program>();
builder.Services.AddDarkWsRedis("my-app:production");
- Используйте уникальный канал для каждого приложения и окружения.
- Мультиплексором и его временем жизни владеет хост; DarkWS его не освобождает.
- Код обработчиков не меняется.
Пакет требует StackExchange.Redis 2.13.17 или новее и протестирован с версиями 2.13.17 и 3.2.1.
Гарантии доставки
Redis Pub/Sub доставляет сообщения не более одного раза. Рассылки, опубликованные, пока экземпляр отключён от Redis (перезапуск, failover, потеря сети), никогда не дойдут до клиентов этого экземпляра, и о пропуске ничто не сообщит.
Считайте рассылки уведомлениями об изменениях, а не источником состояния. После
IConnectionMultiplexer.ConnectionRestored, как и после переподключения клиента,
заставляйте клиентов перезагружать данные из источника истины.
Пропускная способность и порядок
- Каждый экземпляр доставляет рассылки из Redis по одной: следующая рассылка начинается
после того, как предыдущая записана своим локальным получателям. Поэтому медленный
получатель задерживает последующие рассылки на этом экземпляре, пока его запись не
завершится или
BroadcastSendTimeoutеё не оборвёт. BroadcastAsyncи остальные методы рассылки завершаются, когда Redis принимает сообщение, а не после доставки.- Ожидающие сообщения хранятся в неограниченной очереди подписки StackExchange.Redis. Если публикация длительно превышает пропускную способность доставки, растёт потребление памяти. Ограничивайте частоту публикации и размер payload.
Граница доверия
Любой, кто может публиковать в канал, может отправлять произвольные уведомления клиентам на всех экземплярах, включая конкретные сессии и группы.
- Изолируйте Redis на уровне сетевого доступа и ограничьте каналы с помощью ACL.
- Уникальные имена каналов разделяют окружения, но ничего не авторизуют.
- Номера логических баз данных не изолируют каналы Pub/Sub (документация Redis).
MaxMessageSizeBytesограничивает входящие данные WebSocket, а не сообщения Redis. Ограничивайте данные, которые создают ваши публикующие стороны.
Формат сообщений
Конверт Redis использует фиксированные настройки JSON, не зависящие от JsonOptions
приложения:
| Поле | Значение |
|---|---|
target | 0 All, 1 Connection, 2 Session, 3 Group |
targetId | Идентификатор подключения, сессии или группы; null для All |
action | Действие рассылки |
data | Payload приложения, сериализованный с JsonOptions приложения |
Числовые значения целей никогда не меняются. Старые узлы, использующие формат конверта по умолчанию, остаются совместимыми; если старые узлы отправляли конверты с изменёнными именами полей, переводите их на новый канал.
Одна подписка
Redis backplane поддерживает одну активную подписку; DarkWS подписывается при запуске
хоста и отписывается при его остановке. Собственный хост, подписывающийся напрямую,
должен отписаться перед повторной подпиской, поскольку повторный SubscribeAsync
выбрасывает InvalidOperationException. Отписка отменяет токен, переданный
выполняющейся доставке.