Перейти к основному содержимому
Версия: 4.x

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 приложения:

ПолеЗначение
target0 All, 1 Connection, 2 Session, 3 Group
targetIdИдентификатор подключения, сессии или группы; null для All
actionДействие рассылки
dataPayload приложения, сериализованный с JsonOptions приложения

Числовые значения целей никогда не меняются. Старые узлы, использующие формат конверта по умолчанию, остаются совместимыми; если старые узлы отправляли конверты с изменёнными именами полей, переводите их на новый канал.

Одна подписка​

Redis backplane поддерживает одну активную подписку; DarkWS подписывается при запуске хоста и отписывается при его остановке. Собственный хост, подписывающийся напрямую, должен отписаться перед повторной подпиской, поскольку повторный SubscribeAsync выбрасывает InvalidOperationException. Отписка отменяет токен, переданный выполняющейся доставке.