Антипаттерн: повторное использование политики квот

Вы просматриваете документацию Apigee Edge .
Перейдите в документацию Apigee
X.info

Apigee Edge предоставляет возможность настраивать количество разрешенных запросов для API-прокси на определенный период времени с помощью политики квот .

Антипаттерн

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

  • В рамках одного или разных потоков API-прокси
  • В различных целевых конечных точках API-прокси

В результате счетчик квоты будет уменьшаться при каждом выполнении, и ошибки нарушения квоты будут возникать гораздо раньше, чем ожидалось за указанный интервал времени.

Давайте воспользуемся следующим примером, чтобы объяснить, как это работает.

API-прокси

Допустим, у нас есть API-прокси с именем «TestTargetServerQuota», который направляет трафик на два разных целевых сервера в зависимости от пути к ресурсу. И мы хотели бы ограничить трафик API до 10 запросов в минуту для каждого из этих целевых серверов. Вот таблица, иллюстрирующая этот сценарий:

Путь к ресурсу Целевой сервер Квота
/target-us target-US.somedomain.com 10 запросов в минуту
/target-eu target-EU.somedomain.com 10 запросов в минуту

Политика квот

Поскольку квота трафика одинакова для обоих целевых серверов, мы определяем единую политику квотирования с именем «Quota-Minute-Target-Server», как показано ниже:

<!-- /antipatterns/examples/1-8.xml -->
<Quota name="Quota-Minute-Target-Server">
  <Interval>1</Interval>
  <TimeUnit>minute</TimeUnit>
  <Distributed>true</Distributed>
  <Allow count="10"/>
</Quota>

Целевые конечные точки

Давайте применим политику квотирования «Quota-Minute-Target-Server» в предварительном потоке целевой конечной точки «Target-US»:

<!-- /antipatterns/examples/1-9.xml -->
<TargetEndpoint name="Target-US">
  <PreFlow name="PreFlow">
    <Request>
      <Step>
        <Name>Quota-Minute-Target-Server</Name>
      </Step>
    </Request>
  </PreFlow>
  <HTTPTargetConnection>
    <URL>http://target-us.somedomain.com</URL>
  </HTTPTargetConnection>
</TargetEndpoint>

И повторно используйте ту же политику квотирования «Quota-Minute-Target-Server» в предварительном потоке другой целевой конечной точки «Target-EU»:

<!-- /antipatterns/examples/1-10.xml -->
<TargetEndpoint name="Target-EU">
  <PreFlow name="PreFlow">
    <Request>
      <Step>
        <Name>Quota-Minute-Target-Server</Name>
      </Step>
    </Request>
  <Response/>
  </PreFlow>
  <HTTPTargetConnection>
    <URL>http://target-us.somedomain.com</URL>
  </HTTPTargetConnection>
</TargetEndpoint>

Схема входящего потока

Допустим, за первые 30 секунд мы получим в общей сложности 10 API-запросов к этому API-прокси по следующей схеме:

Путь к ресурсу /target-us /target-eu Все
# Запросы 4 6 10

Чуть позже, скажем, через 32 секунды, мы получаем 11-й API-запрос с путем к ресурсу /target-us .

Мы ожидаем, что запрос будет успешно обработан при условии, что у нас осталось 6 API-запросов к целевой конечной точке target-us в соответствии с разрешенной квотой.

Однако в реальности мы получаем Quota violation error .

Причина: Поскольку мы используем одну и ту же политику квотирования для обеих целевых точек, для отслеживания запросов API, поступающих на обе целевые точки, используется один счетчик квот. Таким образом, мы исчерпываем квоту в 10 запросов в минуту в совокупности, а не для каждой целевой точки отдельно.

Влияние

Такая антипаттерновая модель может привести к фундаментальному несоответствию ожиданий, создавая впечатление, что квоты были исчерпаны раньше времени.

Передовая практика

  • Используйте элементы <Class> или <Identifier> , чтобы обеспечить поддержание нескольких уникальных счетчиков путем определения единой политики квот . Давайте переопределим политику квот «Quota-Minute-Target-Server», которую мы только что объяснили в предыдущем разделе, используя заголовок target_id в качестве <Identifier> , как показано ниже:
    <!-- /antipatterns/examples/1-11.xml -->
    <Quota name="Quota-Minute-Target-Server">
      <Interval>1</Interval>
      <TimeUnit>minute</TimeUnit>
      <Allow count="10"/>
      <Identifier ref="request.header.target_id"/>
      <Distributed>true</Distributed>
    </Quota>
    • Мы продолжим использовать эту политику квотирования в обоих целевых регионах — «Target-US» и «Target-EU», как и прежде.
    • Допустим, заголовок target_id имеет значение «US», тогда запросы будут перенаправлены на целевую конечную точку «Target-US».
    • Аналогично, если заголовок target_id имеет значение «EU», то запросы направляются на целевую конечную точку «Target-EU».
    • Таким образом, даже если мы используем одну и ту же политику квотирования на обоих целевых конечных точках, отдельные счетчики квот поддерживаются на основе значения <Identifier> .
    • Таким образом, используя элемент <Identifier> , мы можем гарантировать, что каждая из целевых конечных точек получит разрешенную квоту в 10 запросов.
  • Используйте отдельную политику квот в каждом из потоков/целевых конечных точек/API-прокси, чтобы гарантировать, что вы всегда будете получать разрешенное количество запросов к API. Теперь давайте рассмотрим тот же пример, что и в предыдущем разделе, чтобы увидеть, как мы можем достичь разрешенной квоты в 10 запросов для каждой из целевых конечных точек.
    • Определите отдельную политику квот, по одной для каждой целевой точки «Target-US» и «Target-EU».

      Политика квотирования для целевой конечной точки «Target-US»:

      <!-- /antipatterns/examples/1-12.xml -->
      <Quota name="Quota-Minute-Target-Server-US">
        <Interval>1</Interval>
        <TimeUnit>minute</TimeUnit>
        <Distributed>true</Distributed>
        <Allow count="10"/>
      </Quota>

      Политика квотирования для целевой конечной точки «Target-EU»:

      <!-- /antipatterns/examples/1-13.xml -->
      <Quota name="Quota-Minute-Target-Server-EU">
        <Interval>1</Interval>
        <TimeUnit>minute</TimeUnit>
        <Distributed>true</Distributed>
        <Allow count="10"/>
      </Quota>
    • При определении целевых конечных точек используйте соответствующую политику квотирования, как показано ниже:

      Целевая конечная точка «Target-US»:

      <!-- /antipatterns/examples/1-14.xml -->
      <TargetEndpoint name="Target-US">
        <PreFlow name="PreFlow">
          <Request>
            <Step>
              <Name>Quota-Minute-Target-Server-US</Name>
            </Step>
          </Request>
          <Response/>
        </PreFlow>
        <HTTPTargetConnection>
          <URL>http://target-us.somedomain.com</URL>
        </HTTPTargetConnection>
      </TargetEndpoint>

      Целевая конечная точка «Цель-ЕС»:

      <!-- /antipatterns/examples/1-15.xml -->
      <TargetEndpoint name="Target-EU">
        <PreFlow name="PreFlow">
          <Request>
            <Step>
              <Name>Quota-Minute-Target-Server-EU</Name>
            </Step>
          </Request>
          <Response/>
        </PreFlow>
        <HTTPTargetConnection>
          <URL>http://target-eu.somedomain.com</URL>
        </HTTPTargetConnection>
      </TargetEndpoint>
    • Поскольку для целевых конечных точек «Target-US» и «Target-EU» используется отдельная политика квот, будет вестись отдельный счетчик. Это гарантирует, что для каждой из целевых конечных точек будет достигнута разрешенная квота в 10 API-запросов в минуту.
  • Используйте элементы <Class> или <Identifier> , чтобы обеспечить наличие нескольких уникальных счетчиков.