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

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

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

Антипаттерн

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

  • в одном или разных потоках прокси API;
  • в разных конечных точках API Proxy;

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

Рассмотрим пример.

Прокси 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>

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

Предположим, что в потоке preflow целевой конечной точки Target-US используется правило Quota-Minute-Target-Server:

<!-- /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 секунд для этого прокси API было получено 10 запросов API в следующем порядке:

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

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

Мы ожидаем, что запрос будет выполнен успешно, поскольку у нас ещё есть шесть запросов к 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>

      Целевая конечная точка Target-EU:

      <!-- /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>, чтобы обеспечить работу нескольких уникальных счетчиков.