MBL
Go / Проекты / SessionProxy / SessionProxy: лимиты в Redis и blacklist
Go сложный

SessionProxy: лимиты в Redis и blacklist

projectsredispostgres

Архитектурная схема (archify) →

Почему Redis, а не только Postgres

Лимиты (usage_counters: число запросов, объём трафика, число нарушений) проверяются в Redis на КАЖДЫЙ запрос гостя — это быстрый путь принятия решения «пускать или нет» без похода в реляционную БД на каждый чих. При активной ссылке это могут быть десятки проверок в секунду.

Postgres при этом не выброшен из схемы — он остаётся источником истины для отчётности (реальные агрегаты за всё время) и для восстановления счётчиков, если Redis перезапустили и потерял состояние: при первом обращении к ссылке после рестарта Redis происходит warm load — счётчик подтягивается обратно из Postgres, а не стартует с нуля молча.

Такое разделение — стандартный паттерн «Redis для горячего пути принятия решений, Postgres для истины и восстановления» — работает здесь именно потому, что потеря нескольких секунд точности счётчика (между рестартом Redis и следующим обращением) не критична для бизнес-логики лимитов, в отличие, например, от списания денег.

Правило «самый строгий лимит выигрывает»

Одна shared_link может быть привязана сразу к нескольким access_policies через таблицу-связку link_policies — например, общая политика организации (макс. 1000 запросов) и персональная политика владельца ссылки (макс. 100 запросов).

Эти политики схлопываются в ОДИН эффективный лимит по правилу: берётся минимум по каждому полю (max_requests, max_bytes_transferred, max_ttl_seconds, max_violation_count) среди всех привязанных политик, а NULL в это сравнение не участвует (трактуется как «эта политика не ограничивает данное поле», а не как «ноль»).

Практический пример: если политика A разрешает 1000 запросов без ограничения по трафику (max_bytes_transferred = NULL), а политика B разрешает 100 запросов и 50 МБ трафика — эффективный лимит будет 100 запросов (минимум из 1000 и 100) и 50 МБ трафика (единственное заданное значение, раз у A оно NULL).

Blacklist проверяется по правильному пути

Пути в blacklisted_endpoints записаны и проверяются в терминах реального пути НА ЦЕЛЕВОМ сайте (например, /settings), а не по обёрнутому гостевому URL прокси (/r/{token}/settings).

Если бы проверка шла по гостевому URL, было бы достаточно любой обфускации на стороне клиента прокси (лишний параметр запроса, изменённый регистр, кодирование части пути), чтобы обойти правило — сама структура /r/{token}/... не гарантирует однозначного соответствия одному и тому же реальному пути. Проверка по факту резолвленного целевого пути устраняет этот класс обходов целиком, а не патчит его точечно под конкретный обнаруженный трюк.

Пустой список заблокированных методов у правила в endpoint_blocked_methods трактуется как «блокировать ВСЕ методы для этого пути», непустой список — как «блокировать только перечисленные» (например, разрешить GET /export, но заблокировать POST /export, если экспорт можно смотреть, но не инициировать через прокси).

Самопроверка 0 / 3
Знаю, почему лимиты проверяются в Redis, а не напрямую в Postgres на каждый запрос
Могу объяснить правило "самый строгий лимит выигрывает" на конкретном примере
Понимаю, почему blacklist проверяется по пути НА целевом сайте, а не по гостевому URL
Как усвоено?