← Cache & Workers

Rate-limit

cache-workers · workzone

Один примитив ограничения темпа на всю платформу: модули не считают лимиты сами, а спрашивают общий счётчик. Сам счётчик и его потребители — разные заботы; ниже первый, затем второй.

Общий примитив

Общий сервис ограничения темпа на всю платформу. Атомарность — Lua-скрипт в Redis считает и списывает за один заход, без гонок между воркерами. Сервис даёт две стратегии под разную задачу: token-bucket (всплеск плюс средний темп) и скользящее окно (точный счёт событий за интервал) — потребитель выбирает, инфраструктура счётчика общая. Порог задаётся статически (платформенный дефолт плюс override через конфиг, без хардкода) и динамически — потребитель вправе менять темп в рантайме, что нужно адаптивным (см. Harvester ниже). Счётчик живёт в redis-durable: переживает рестарт и не вытесняется под памятью. Грубый сетевой rate-limit на Nginx — Auth & Security — стоит внешним рубежом перед прикладным: режет шторм пакетов до того, как тот дойдёт до приложения. Этот примитив — дом правила «лимит частоты» свода HTTP API.

1 Ёмкость — максимум токенов в корзине (пиковый всплеск).
2 Пополнение — токены капают по времени до ёмкости (средний темп).
3 Запрос берёт токен — есть свободный → пропуск, токен списан.
4 Корзина пуста → отказ; ждать пополнения.

Потребители

Потребитель Что ограничивает Природа порога Стратегия Окно / TTL Режим отказа
Harvester темп запросов к внешним источникам адаптивная — задаёт чужой источник token-bucket с AIMD — плавный разгон, резкий сброс на отказе часами, по области (аккаунт / площадка) fail-open
Auth & Security перебор логина фиксированная — задаёт безопасность скользящее окно по IP + задержка per-account (email) 15 мин (скольз.) fail-closed
Auth & Security прикладной API (ключи) фиксированная — задаёт политика ключа token-bucket, единый потолок на ключ (квоты по роли — v2) минута fail-open
Входящее мессенджера (Slack · Telegram · Mattermost) объём входящих событий — публичный webhook-эндпоинт; у Mattermost вебхука нет, поток его слушателя ограничен по каналу фиксированная — задаёт безопасность скользящее окно по IP / источнику / каналу минута (скольз.) fail-closed
Режим отказа — свойство потребителя, не примитива. При недоступности redis-durable троттлинг пропускает запрос (лимит — лишь оптимизация темпа), а защита блокирует: для brute-force fail-open открыл бы окно перебора, поэтому fail-closed. Дефолт безопасный — fail-closed; послабление до fail-open потребитель объявляет осознанно.
Отказ прикладному вызову возвращается как HTTP 429 с Retry-After — клиент узнаёт, когда повторить; внутреннему потребителю (Harvester) тот же отказ — сигнал притормозить.
Отдельная корзина под дорогие LLM-вызовы — v2: темп инференса режется не наравне с обычным API, а своим лимитом по стоимости.