Antywzór: ponowne wykorzystywanie zasad dotyczących limitów

Wyświetlasz dokumentację Apigee Edge.
Przejdź do dokumentacji Apigee X.
info

Apigee Edge umożliwia skonfigurowanie liczby dozwolonych żądań do proxy interfejsu API w określonym czasie za pomocą zasady dotyczącej limitów.

Antywzorzec

Jeśli zasada dotycząca limitów jest używana ponownie, licznik limitów będzie zmniejszany za każdym razem, gdy zasada dotycząca limitów zostanie wykonana, niezależnie od tego, gdzie jest używana. Oznacza to, że jeśli zasada dotycząca limitów jest używana ponownie:

  • w tym samym lub różnych przepływach proxy interfejsu API,
  • w różnych docelowych punktach końcowych proxy interfejsu API,

licznik limitów będzie zmniejszany za każdym razem, gdy zasada zostanie wykonana, a błędy naruszenia limitów będą występować znacznie wcześniej niż oczekiwano w określonym przedziale czasu.

Aby wyjaśnić, jak to działa, użyjemy tego przykładu.

Proxy interfejsu API

Załóżmy, że mamy proxy interfejsu API o nazwie „TestTargetServerQuota”, które kieruje ruch do 2 różnych serwerów docelowych na podstawie ścieżki zasobu. Chcemy ograniczyć ruch interfejsu API do 10 żądań na minutę dla każdego z tych serwerów docelowych. Oto tabela przedstawiająca ten scenariusz:

Ścieżka zasobu Serwer docelowy Quota
/target-us target-US.somedomain.com 10 żądań na minutę
/target-eu target-EU.somedomain.com 10 żądań na minutę

Zasada dotycząca limitów

Ponieważ limit ruchu jest taki sam w przypadku obu serwerów docelowych, definiujemy jedną zasadę dotyczącą limitów o nazwie „Quota-Minute-Target-Server”, jak pokazano poniżej:

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

Docelowe punkty końcowe

Użyjmy zasady dotyczącej limitów „Quota-Minute-Target-Server” w przepływie wstępnym docelowego punktu końcowego „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>

Użyjmy też tej samej zasady dotyczącej limitów „Quota-Minute-Target-Server” w przepływie wstępnym innego docelowego punktu końcowego „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>

Wzorzec ruchu przychodzącego

Załóżmy, że w ciągu pierwszych 30 sekund otrzymujemy łącznie 10 żądań do interfejsu API w tym proxy interfejsu API w tym wzorcu:

Ścieżka zasobu /target-us /target-eu Wszystkie
Liczba żądań 4 6 10

Nieco później, powiedzmy po 32 sekundach, otrzymujemy 11. żądanie do interfejsu API ze ścieżką zasobu /target-us.

Oczekujemy, że żądanie zostanie zrealizowane, ponieważ zgodnie z dozwolonym limitem mamy jeszcze 6 żądań do interfejsu API dla docelowego punktu końcowego target-us.

W rzeczywistości jednak otrzymujemy Quota violation error.

Przyczyna: ponieważ w obu docelowych punktach końcowych używamy tej samej zasady dotyczącej limitów, do śledzenia żądań do interfejsu API docierających do obu docelowych punktów końcowych używany jest jeden licznik limitów. W ten sposób wyczerpujemy limit 10 żądań na minutę łącznie, a nie dla poszczególnych docelowych punktów końcowych.

Wpływ

Ten antywzorzec może spowodować zasadniczą niezgodność oczekiwań, co prowadzi do przekonania, że limity zostały wyczerpane przed czasem.

Sprawdzona metoda

  • Aby zapewnić utrzymywanie wielu unikalnych liczników, zdefiniuj jedną zasadę dotyczącą limitów i użyj elementów <Class> lub <Identifier>. Zdefiniujmy ponownie zasadę dotyczącą limitów „Quota-Minute-Target-Server”, którą opisaliśmy w poprzedniej sekcji, używając nagłówka target_id jako <Identifier>, jak pokazano poniżej:
    <!-- /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>
    • Nadal będziemy używać tej zasady dotyczącej limitów w obu docelowych punktach końcowych „Target-US” i „Target-EU”, tak jak wcześniej.
    • Jeśli nagłówek target_id ma wartość „US”, żądania są kierowane do docelowego punktu końcowego „Target-US”.
    • Podobnie, jeśli nagłówek target_id ma wartość „EU”, żądania są kierowane do docelowego punktu końcowego „Target-EU”.
    • Dlatego nawet jeśli używamy tej samej zasady dotyczącej limitów w obu docelowych punktach końcowych, utrzymywane są oddzielne liczniki limitów na podstawie wartości <Identifier>.
    • Dzięki temu, że używamy elementu <Identifier>, możemy mieć pewność, że każdy z docelowych punktów końcowych otrzyma dozwolony limit 10 żądań.
  • Używaj osobnej zasady dotyczącej limitów w każdym przepływie, docelowym punkcie końcowym lub proxy interfejsu API, aby mieć pewność, że zawsze otrzymasz dozwoloną liczbę żądań do interfejsu API. Przyjrzyjmy się teraz temu samemu przykładowi, który został użyty w poprzedniej sekcji, aby zobaczyć, jak możemy osiągnąć dozwolony limit 10 żądań dla każdego z docelowych punktów końcowych.
    • Zdefiniuj oddzielną zasadę dotyczącą limitów – po jednej dla docelowych punktów końcowych „Target-US” i „Target-EU”.

      Zasada dotycząca limitów dla docelowego punktu końcowego „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>

      Zasada dotycząca limitów dla docelowego punktu końcowego „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>
    • Użyj odpowiedniej zasady dotyczącej limitów w definicji docelowych punktów końcowych, jak pokazano poniżej:

      Docelowy punkt końcowy „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>

      Docelowy punkt końcowy „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>
    • Ponieważ w docelowych punktach końcowych „Target-US” i „Target-EU” używamy osobnych zasad dotyczących limitów, będzie utrzymywany oddzielny licznik. Dzięki temu dla każdego z docelowych punktów końcowych otrzymujemy dozwolony limit 10 żądań do interfejsu API na minutę.
  • Aby zapewnić utrzymywanie wielu unikalnych liczników, użyj elementów <Class> lub <Identifier>.