Стратегии формирования / регулирования трафика API для изоляции клиентов

Я начну свой вопрос с предоставления некоторого контекста о том, что мы делаем и с какими проблемами сталкиваемся.

  • В настоящее время мы создаем SaaS (размещенный на Amazon AWS), который состоит из нескольких микросервисов, расположенных за шлюзом API (мы используем Kong).
  • Шлюз обрабатывает аутентификацию (через потребителей с ключами API) и предоставляет API-интерфейсы этих микросервисов, о которых я упоминал, все из которых не имеют состояния (нет сеансов, файлов cookie и т.п.).
  • Каждая служба развертывается с использованием служб ECS (один или несколько контейнеров докеров для каждой службы, работающей на одной или нескольких машинах EC2) и балансировки нагрузки с помощью Amazon Application Load Balancer (ALB).
  • Все арендаторы (клиенты) используют одну и ту же среду, то есть одни и те же машины и ресурсы. Учитывая нашу бизнес-модель, мы ожидаем, что у нас будет мало арендаторов, кроме «крупных» (на первых порах).
  • Большинство запросов к этим службам переводятся в интенсивное использование ресурсов (в основном ЦП) на время выполнения запроса. Время, необходимое для обслуживания одного запроса, находится в диапазоне 2-10 секунд (а не мс, как в традиционных веб-приложениях). Это означает, что мы обслуживаем относительно мало запросов в минуту, при этом обработка каждого из них требует времени (фоновая или пакетная обработка невозможны).

Прямо сейчас у нас нет стратегии, чтобы ограничить или задушить количество запросов, которые клиент может сделать за определенный период времени. Принимая во внимание последние два приведенных выше соображения, легко увидеть, что это проблема, поскольку для арендатора почти тривиально сделать больше запросов, чем мы можем обработать, что приводит к ухудшению качества обслуживания (даже для других арендаторов из-за подход общих ресурсов).

Мы думаем о стратегиях ограничения / дросселирования или в целом подготовки системы к «изоляции» клиентов, чтобы один клиент не мог ухудшить производительность других, делая больше запросов, чем мы можем обработать:

  • Ограничение скорости: определите максимальное количество запросов в минуту, которое может сделать клиент. Если поступят новые запросы, отбросьте их. У Конга даже есть плагин для этого. К сожалению, мы используем модель ценообразования «плата за запрос», и бизнес не позволяет нам использовать эту стратегию, потому что мы хотим обработать как можно больше запросов, чтобы получить за них деньги. Если лишние запросы потребуют больше времени для клиента, это нормально.
  • Изоляция клиента: создайте изолированную среду для каждого клиента. От этого тоже отказались, так как он усложняет обслуживание и ведет к меньшему использованию ресурсов и более высоким затратам.
  • Автоматическое масштабирование. Увеличьте количество машин, которые будут поглощать всплески. По нашему опыту, Amazon ECS не очень быстро справляется с этим, и к тому времени, когда эти новые машины будут готовы, будет уже слишком поздно.
  • Регулирование запросов: использование таких алгоритмов, как Leaky Bucket или Token Bucket на уровне шлюза API, чтобы гарантировать, что запросы поступают в службы с известной скоростью, с которой мы можем справиться.

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

Если прибывает пакет, избыточные запросы будут помещены в очередь (до предела), а затем выпущены с фиксированной скоростью (с использованием дырявого ведра или аналогичного алгоритма). Это гарантирует, что клиент не сможет повлиять на производительность других клиентов, поскольку запросы будут попадать в службы с заранее определенной скоростью. В идеале разрешенная частота запросов должна быть «динамической» таким образом, чтобы клиент мог использовать некоторые «запросы в минуту» других клиентов, которые их не используют (в пределах безопасности). Я считаю, что это называется алгоритмом «Утечка с динамической скоростью». Цель состоит в том, чтобы максимально использовать ресурсы.

Мои вопросы:

  • Является ли предлагаемая стратегия жизнеспособной? Знаете ли вы какие-либо другие жизнеспособные стратегии для этого варианта использования?
  • Существует ли услуга с открытым исходным кодом, коммерческая или SaaS-служба, которая может предоставить эти возможности формирования трафика? Насколько я знаю, Kong или Tyk не поддерживают ничего подобного, поэтому ... Есть ли какой-либо другой API шлюз что делает?
  • Если Kong не поддерживает это, насколько сложно реализовать что-то вроде того, что я описал как плагин? Мы должны принять во внимание, что для этого потребуется какое-то общее состояние (например, с помощью Redis ), поскольку мы используем несколько экземпляров Kong (для балансировки нагрузки и высокой доступности).

Большое спасибо, Микель.


person Mikel    schedule 01.07.2018    source источник


Ответы (1)


Управление очередью запросов на стороне шлюза - действительно сложная вещь, и, вероятно, основная причина, по которой она не реализована в этих шлюзах, заключается в том, что это действительно сложно сделать правильно. Вам необходимо обрабатывать все случаи распределенной системы, и, кроме того, это сложно сделать «безопасным», потому что «медленные» клиенты быстро потребляют машинные ресурсы.

Такой шаблон обычно выгружается в клиентские библиотеки, поэтому, когда клиент достигает кода состояния ограничения скорости, он использует что-то вроде экспоненциальной техники отсрочки для повторных запросов. Его проще масштабировать и внедрять.

Не могу сказать о Конге, но в данном случае Tyk предоставляет два основных числа, которыми вы можете управлять: квота - максимальное количество запросов, которые клиент может сделать за данный период времени, и ограничения скорости - защита безопасности. Вы можете установить ограничение скорости 1) для «политики», например, для группы потребителей (например, если у вас есть несколько уровней вашего сервиса с разными допустимыми ограничениями использования / скорости), 2) для отдельного ключа 3) Глобально для API (работает вместе с лимитами ключевой ставки). Так, например, вы можете установить умеренные ограничения скорости клиентов и ограничить общий лимит с помощью глобальной настройки API.

Если вы хотите полностью динамическую схему и пересчитать лимиты на основе нагрузки кластера, это должно быть возможно. Вам нужно будет где-то написать и запустить этот планировщик, время от времени он будет выполнять повторный расчет на основе текущего общего использования (который Tyk рассчитывает для вас, и вы получаете его от Redis) и будет разговаривать с Tyk API, повторяя через все ключи (или политики) и динамически обновляя их пределы скорости.

Надеюсь, это имеет смысл :)

person Leonid Bugaev    schedule 03.07.2018