Конфигурация и ограничения
Настраивайте DarkWsOptions через AddDarkWs, services.Configure<DarkWsOptions>,
привязку конфигурации или PostConfigure; они применяются в стандартном порядке Options:
builder.Services.AddDarkWs(options => {
options.MaxMessageSizeBytes = 256 * 1024;
options.MaxConcurrentRequestsPerConnection = 8;
options.ShutdownTimeout = TimeSpan.FromSeconds(5);
});
builder.Services.Configure<DarkWsOptions>(builder.Configuration.GetSection("DarkWs"));
Опции валидируются при первом разрешении и при запуске хоста; недопустимые значения
приводят к OptionsValidationException. DarkWS читает их через IOptions<DarkWsOptions>,
поэтому значения фиксируются при первом разрешении; изменение конфигурации во время
работы не перенастраивает DarkWS.
Опции
| Опция | По умолчанию | Значение |
|---|---|---|
MaxMessageSizeBytes | 1 MiB | Максимальный размер полного входящего сообщения с учётом всех фрагментов |
JsonOptions | JsonSerializerDefaults.Web | Сериализация конвертов и payload |
MaxConcurrentRequestsPerConnection | 16 | Число одновременно выполняемых действий на одном подключении |
KeepAliveInterval | 30 s | Интервал keep-alive транспорта |
KeepAliveTimeout | 30 s | Дедлайн PONG на уровне транспорта (.NET 9 и новее) |
ReceiveIdleTimeout | 2 min | Дедлайн ожидающего чтения (.NET 8) |
SendTimeout | 30 s | Ожидание блокировки отправки плюс запись в сокет |
BroadcastSendTimeout | 10 s | Дедлайн записи рассылки для каждого получателя |
ShutdownTimeout | 10 s | Обработчики, хуки закрытия middleware и close handshake при остановке |
AuthenticationQueryParameter | token | Параметр запроса, передаваемый аутентификатору при upgrade |
InvalidActionError | darkws:error:invalid-action | Код для неизвестных действий |
InvalidRequestError | darkws:error:invalid-request | Код для некорректных запросов и payload |
AuthorizationRequiredError | darkws:error:authorization-required | Код для анонимных вызовов защищённых действий |
RequestFailedError | darkws:error:request-failed | Код для непредвиденных сбоев |
AuthenticationFailedError | darkws:error:authentication-failed | Сохранена для совместимости исходного кода; не используется, поскольку auth: всегда отвечает auth:failed |
Все таймауты должны быть положительными и не превышать 4294967294 миллисекунды.
MaxMessageSizeBytes и MaxConcurrentRequestsPerConnection должны быть положительными,
JsonOptions не может быть null, а AuthenticationQueryParameter и коды ошибок не
могут быть пустыми.
Размер сообщения
MaxMessageSizeBytes проверяется до разбора JSON и охватывает все фрагменты
сообщения, включая команды аутентификации. Сообщение, размер которого ровно равен
лимиту, принимается. Более крупное сообщение закрывает подключение со статусом 1009
(Message Too Big), и частично полученное сообщение не обрабатывается. Повышайте лимит,
только если приложение действительно отправляет большие сообщения: вместе с ним растёт
память на подключение.
Конкурентность запросов и backpressure
Каждое подключение одновременно выполняет до MaxConcurrentRequestsPerConnection
запросов. Когда столько запросов уже выполняется, подключение перестаёт читать, пока
один из них не завершится. Ни один запрос не отклоняется, и ошибка занятости не
отправляется; вместо этого сообщения клиента ждут в буферах сокета и сети.
- Текстовые
ping,auth:иlogoutчитаются тем же циклом, поэтому они тоже ждут. При длительной нагрузке может истечь таймаут pong на клиенте. auth:иlogoutобрабатываются в порядке чтения, не дожидаясь выполняющихся запросов.
При выборе лимитов закладывайте память на выполняемые запросы, каждый размером до
MaxMessageSizeBytes, умноженную на ожидаемое число подключений.
DarkWS ограничивает работу только внутри одного подключения. Общее число подключений и лимиты на пользователя или IP задавайте в хосте или reverse proxy.
Проверка активности
DarkWS обнаруживает «мёртвые» пиры по-разному в зависимости от рантайма:
- .NET 9 и 10: сервер отправляет транспортные PING каждые
KeepAliveIntervalи обрывает подключение, если PONG не пришёл в течениеKeepAliveTimeout. - .NET 8: каждое ожидающее чтение из сокета ограничено
ReceiveIdleTimeout, который сбрасывается при получении каждого фрагмента. Простаивающие клиенты должны отправлять трафик приложения в пределах этого времени. Клиенты DarkWS по умолчанию отправляют текстовыйpingкаждые 30 секунд. Транспортные PONG не учитываются. Таймер работает только во время ожидающего чтения, поэтому он приостановлен, пока перегруженное подключение не читает.
.NET-клиент также обнаруживает «мёртвый» сервер с помощью собственного таймаута pong.
Отправка и остановка
SendTimeoutохватывает ожидание блокировки отправки подключения и запись в сокет. По истечении сокет обрывается.- Рассылки используют более короткий
BroadcastSendTimeoutдля каждого получателя, поэтому медленный клиент не может надолго задержать рассылку. - При остановке подключение сразу удаляется из хранилища, а токены обработчиков
отменяются.
ShutdownTimeout— единый общий дедлайн для незавершённых обработчиков, хуков закрытия middleware и close handshake; если close handshake не завершился вовремя, сокет обрывается.
JSON
JsonOptions общий для всех обработчиков. По умолчанию свойства прикладных DTO
используют camelCase, а чтение не учитывает регистр. Имена полей конверта id,
action, data и error закреплены атрибутами JsonPropertyName и не меняются от
политики именования. Клиенты должны соблюдать схему DTO внутри data.
Конверт Redis использует независимые настройки сериализации.
Логирование
- Успешные действия и некорректные запросы клиентов логируются на уровне
Debug. - Непредвиденные сбои обработчиков и исключения, выброшенные аутентификатором во время
auth:, логируются как предупреждения. - Сообщения исключений обработчиков попадают в лог, но никогда не отправляются клиентам.