Защита от перегрузки — Versola Docs
/docs
До 1.00.7.5versola.ioGitHub

Защита от перегрузки

Как edge быстро отказывает в лишних запросах вместо очереди, три режима, приоритеты, что значит каждое число, как задать их в консоли или через API, как включать и настраивать.

Когда к edge приходит больше запросов, чем он обслужит, лучше сразу отказать в лишних, чем держать их в очереди, пока не замедлится все. Защита от перегрузки делает именно это и настраивается для каждого edge из central, поэтому менять ее можно без передеплоя. Нужен зарегистрированный edge и оператор с правом edges:manage; с edges:read настройки видны, но не меняются.

Что она защищает

Два ограничителя, у каждого свой режим и свои настройки:

ОграничительГдеЧто ограничивает
Inbound admissionedgeЗапросы в обработке на edge. Выше лимита запрос получает 503 и заголовок Retry-After.
Outbound callsкаждый сервис, на каждого peerВызовы edge к auth и к вашим backend’ам ресурсов: вызовы в обработке, ограниченное ожидание, таймаут запроса, circuit breaker и бюджет повторов. Отказ — 503, слишком долгий вызов — 504.

central исходящий ограничитель никогда не ограничивает, поэтому сервис может дождаться своей конфигурации при старте, а до конца старта ничего не применяется.

Три режима

РежимЧто происходит
offНичего не считается, не изучается и не отклоняется.
shadowEdge считает, что отклонил бы enforce, и ничего не отклоняет. Это значение по умолчанию: после обновления ничего не меняется, пока вы не выберете другое.
enforceEdge отклоняет все, что выше лимита.

Приоритеты

Inbound admission не равняет все запросы. Запрос принимается, пока число запросов в обработке ниже доли лимита его уровня, поэтому верх лимита остается свободным для более важной работы:

  1. Новый вход (самый дорогой, работа еще не начата): отклоняется первым. Может занять start share лимита, по умолчанию 0,65.
  2. Уже начатая работа (обмен кода, выход): отклоняется следующей. Может занять continuation share, по умолчанию 0,85.
  3. Проксируемые вызовы к вашему API: отклоняются последними. Могут занять весь лимит.
  4. Health и метрики, синхронизация конфигурации и back-channel logout: не считаются и не отклоняются никогда.

Что значат числа

Лимит не придуман человеком. Edge выучивает его по времени вызовов и по тому, насколько поздно его собственный executor запускает таймер: лимит сжимается, когда вызовы замедляются или executor «залипает», и растет обратно, пока вызовы быстрые, между нижним и верхним пределом. Он выучивается, пока режим inbound не off; в shadow лимит выучивается, но ничего не отклоняется. Starting limit — лишь точка старта (она зажимается в пределы).

Каждое поле необязательно. Пустое поле не отправляется, и edge берет значение своего деплоя: переменную окружения HTTP_ADMISSION_* или HTTP_CLIENT_GUARD_*, если edge ее задает, иначе встроенное значение по умолчанию. Заданное поле не «прибивает» остальные.

Inbound

ПолеПо умолчаниюБаза из окруженияСмысл
modeshadowHTTP_ADMISSION_MODEoff, shadow или enforce.
maxInFlight (Starting limit)256HTTP_ADMISSION_MAX_IN_FLIGHTС чего начинается выученный лимит, от 1 до 100000.
continuationShare0,85HTTP_ADMISSION_CONTINUATION_SHAREДоля лимита для уже начатой работы, от 0,01 до 1.
startShare0,65HTTP_ADMISSION_START_SHAREДоля лимита для нового входа, от 0,01 до 1, не больше continuationShare.
retryAfterSeconds1HTTP_ADMISSION_RETRY_AFTERRetry-After в отказе, от 1 до 60 с.
adaptive.minLimit16нетВыученный лимит не опускается ниже, от 1 до 100000.
adaptive.maxLimit1024нетВыученный лимит не поднимается выше, от 1 до 100000, не меньше minLimit.
adaptive.tolerance1,5нетНасколько медленнее обычного может стать вызов, прежде чем лимит начнет сжиматься, от 1 до 5.
adaptive.smoothing0,2нетКакая доля новой оценки заменяет лимит, от 0,01 до 1.
adaptive.lagTargetMillis50нетНасколько поздно executor может запустить таймер, чтобы это еще не считалось остановкой, от 5 до 10000 мс.

Starting limit ниже minLimit или выше maxLimit стартует с ближайшей границы.

Outbound

ПолеПо умолчаниюБаза из окруженияСмысл
modeshadowHTTP_CLIENT_GUARD_MODEoff, shadow или enforce.
maxConcurrentразмер пула соединений (128)HTTP_CLIENT_GUARD_MAX_CONCURRENTВызовы в обработке к одному peer, от 1 до 100000.
maxQueue256HTTP_CLIENT_GUARD_MAX_QUEUEСколько вызовов могут ждать место; еще один отклоняется сразу, от 1 до 100000.
queueTimeoutMillis1000HTTP_CLIENT_GUARD_QUEUE_TIMEOUTСколько вызов максимум ждет место, от 1 до 600000 мс.
requestTimeoutMillis10000HTTP_CLIENT_GUARD_REQUEST_TIMEOUTСколько вызов может идти до заголовков ответа, от 1 до 600000 мс.
breaker.enabledвыключеннетCircuit breaker выключен, пока не включен.
breaker.failureRatio0,5нетДоля неудачных вызовов (ошибка транспорта, таймаут, 502, 503, 504), открывающая цепь, от 0,01 до 1.
breaker.minCalls20нетСколько вызовов должно быть в окне, прежде чем доля учитывается, от 1 до 10000.
breaker.windowSeconds10нетПериод, за который считается доля, от 1 до 300 с.
breaker.openSeconds5нетСколько цепь отказывает сразу, прежде чем пробовать, от 1 до 600 с.
breaker.probeCalls3нетСколько вызовов пропускается для проверки полуоткрытой цепи, от 1 до 100.
retryBudget.ratio0,1нетСколько повторов разрешено на сделанный вызов, от 0 до 1.
retryBudget.minPerSecond5нетСколько повторов в секунду разрешено всегда, от 0 до 1000.

Очередь и таймауты действуют только в enforce.

Настройка в консоли

Откройте Edges, откройте нужный edge и нажмите Edit на карточке Overload protection. Редактор открывается в боковой панели: раздел inbound и раздел outbound, в каждом короткая подсказка по настройке, режим на выбор из Deployment default, Off, Shadow и Enforce, а у остальных полей под ними написано значение по умолчанию (и его переменная окружения). Редко меняемые tolerance, smoothing и lag target лежат под Advanced.

Карточка Overload protection показывает, что задано здесь; все остальное берется из деплоя
Панель edge с карточкой Overload protection: inbound Enforce и outbound Shadow, заданные здесь, поля, отличающиеся от деплоя, и кнопка Reset to deployment defaults
Каждое поле необязательно; значение, к которому оно откатывается, написано под ним
Панель Edit overload protection: разделы inbound и outbound с режимами, полями, значениями по умолчанию под каждым полем и кнопками Reset to deployment defaults, Cancel и Save

Редактор проверяет диапазоны по ходу ввода теми же сообщениями, что и central, и не отправляет политику, которая их нарушает. Save overload protection отправляет только заполненные поля. Reset to deployment defaults после подтверждения удаляет политику, и edge возвращается к значениям своего деплоя.

Изменение доходит до edge при следующей синхронизации конфигурации, в пределах интервала обновления (по умолчанию 5 минут). Пока central недоступен, edge держит последнюю полученную политику. Политику, не прошедшую проверку, central отклоняет, а edge не применяет.

Настройка через API

PATCH /configuration/edges/policies?edgeId=<id> с секцией overload заменяет политику целиком; "overload": null удаляет ее, а остальные секции edge (accessLog, rateLimits) остаются как есть. Секция — схема OverloadPolicy в OpenAPI-файле central. Поля, которых нет в схеме, игнорируются. expectedRevisions и dryRun описаны на странице Лимиты запросов.

{
  "overload": {
    "inbound": {
      "mode": "enforce",
      "adaptive": { "maxLimit": 1536 }
    },
    "outbound": { "mode": "shadow" }
  }
}

Значение вне диапазона дает 400 без тела; первая найденная проблема — в журнале central.

Как включать

  1. Оставьте shadow, значение по умолчанию, минимум на сутки реального трафика с пиком.
  2. Смотрите http_admission_refused_total{mode="shadow"}. Около нуля при свободных ресурсах — лимит не мешает. Много shadow-отказов на пике — enforce отсек бы этот трафик: сначала поднимите adaptive.maxLimit или добавьте мощности.
  3. Переведите inbound mode в enforce на одном edge. Понаблюдайте за отказами, пропускной способностью и задержкой весь пик, затем включайте остальные.
  4. Outbound включайте на шаг позже тем же способом, а circuit breaker — последним.

Что видит клиент в enforce: 503 и Retry-After: <retryAfterSeconds>. Клиент должен подождать не меньше этого времени, добавить jitter и повторить ограниченное число раз; повтор без паузы только усиливает перегрузку.

Метрики

МетрикаЧто показывает
http_admission_refused_total{tier,mode}Отказы по уровням; в shadow — что отклонил бы enforce.
http_admission_in_flight, http_admission_in_flight_peakЗапросы в обработке сейчас и наибольшее значение с прошлого замера.
http_admission_limitДействующий выученный лимит.
http_admission_adaptive_limit_ratioВыученный лимит к maxLimit; около 1 — запас есть, низкое — edge зажат.
http_admission_rtt_seconds{tier}Среднее время вызова за последнее окно по уровням.
http_executor_lag_secondsХудшее опоздание таймера на 10 мс за последнюю секунду.
http_client_guard_rejected_total{mode}Исходящие отказы; в shadow — что отклонил бы enforce.
http_client_guard_in_flight, _waiting, _breaker_stateИсходящие вызовы в обработке, в ожидании и состояние цепи.

Подстройка

СимптомЧто менять
Отказы в enforce, а pod простаиваетПоднимите adaptive.minLimit, а если http_admission_limit упирается в верх, — adaptive.maxLimit.
Задержка растет раньше, чем edge начинает отказыватьСнизьте adaptive.tolerance (ближе к 1) или adaptive.lagTargetMillis.
Лимит колеблется вверх и внизСнизьте adaptive.smoothing.
Новые входы отклоняются, а проксируемые вызовы проходятТак и задумано. Поднимайте startShare, только если входы важнее проксируемых вызовов.
Клиенты повторяют запросы без паузы после отказаПоднимите retryAfterSeconds.
Вызовы к медленному backend копятсяСнизьте outbound maxConcurrent и поставьте requestTimeoutMillis чуть выше p99 backend’а.
Падающий backend продолжает получать вызовыВключите circuit breaker и подберите failureRatio и openSeconds.

Что дальше