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

Przeglądasz dokumentację Apigee Edge.
Otwórz dokumentację Apigee X.
Informacje

Apigee Edge umożliwia skonfigurowanie liczby dozwolonych żądań dla serwera proxy interfejsu API przez określony czas przy użyciu zasady limitów.

Antywzór

Jeśli ponownie użyjesz zasady limitów, licznik limitów będzie zmniejszany przy każdym wykonaniu tej zasady niezależnie od tego, gdzie jest ona używana. Oznacza to, że jeśli zasada dotycząca limitów jest używana ponownie:

  • W ramach tego samego procesu lub różnych przepływów w ramach serwera proxy interfejsu API
  • W różnych docelowych punktach końcowych serwera proxy interfejsu API

Od tego momentu przy każdym uruchomieniu licznik czasu będzie zmniejszany, przez co w określonym przedziale czasu błędy dotyczące naruszenia limitu będą pojawiać się znacznie wcześniej niż powinny.

Przeanalizujmy poniższy przykład, aby wyjaśnić działanie tej funkcji.

Serwer proxy API

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

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

Zasady dotyczące limitów

Ponieważ limit ruchu jest taki sam w przypadku obu serwerów docelowych, definiujemy jedną zasadę dotyczącą limitów o nazwie „Limit-Minuty-Docelowy serwer”, 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

Wykorzystajmy zasadę limitu „limit-minutowy-serwer docelowy” na etapie wstępnym w przypadku 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>

Zastosuj też tę samą zasadę dotyczącą limitów „Limit-Minuty-Serwer docelowy” we wstępnym procesie w przypadku 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 tego serwera proxy interfejsu API według tego wzoru:

Ścieżka zasobu /target-us /target-eu Wszystko
# prośby 4 6 10

Po 32 sekundach otrzymujemy 11 żądanie do interfejsu API ze ścieżką zasobu jako /target-us.

Oczekujemy, że żądanie zostanie zrealizowane, zakładając, że nadal mamy 6 żądań do interfejsu API dotyczących docelowego punktu końcowego target-us w ramach dozwolonego limitu.

W rzeczywistości jednak otrzymujemy Quota violation error.

Powód: w obu docelowych punktach końcowych stosujemy te same zasady dotyczące limitów, więc do śledzenia żądań do interfejsu API trafiających do obu docelowych punktów końcowych służy licznik jednego limitu. W związku z tym limit 10 żądań na minutę wyczerpuje się łącznie, a nie w przypadku poszczególnych docelowych punktów końcowych.

Wpływ

Taki antywzorzec może prowadzić do całkowitej niezgodności z oczekiwaniami, przez co wydaje się, że limity wyczerpały się z wyprzedzeniem.

Sprawdzona metoda

  • Użyj elementów <Class> lub <Identifier>, aby utrzymywać wiele liczników unikalnych użytkowników przez zdefiniowanie jednej zasady limitów. Zdefiniujmy ponownie zasadę dotyczącą limitów „Limit-Minuty-Docelowy serwer”, którą przed chwilą omówiliśmy w poprzedniej sekcji, używając nagłówka target_id jako elementu <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>
    
    • Będziemy nadal stosować te zasady dotyczące limitów zarówno w docelowych punktach końcowych „Target-US”, jak i „Target-EU”.
    • Załóżmy teraz, że nagłówek target_id zawiera wartość „US”, wtedy żądania są kierowane do docelowego punktu końcowego „Target-US”.
    • Podobnie jeśli nagłówek target_id zawiera wartość „EU”, żądania są kierowane do docelowego punktu końcowego „Target-EU”.
    • Dlatego nawet jeśli w obu docelowych punktach końcowych stosujemy te same zasady dotyczące limitów, utrzymujemy osobne liczniki limitów na podstawie wartości <Identifier>.
    • Dlatego używając elementu <Identifier>, możemy zagwarantować, że każdy z docelowych punktów końcowych otrzyma dozwolony limit 10 żądań.
  • Aby mieć pewność, że zawsze będziesz otrzymywać dozwoloną liczbę żądań do interfejsu API, używaj osobnych zasad dotyczących limitów w każdym przepływie pracy/w docelowych punktach końcowych/serwerach proxy API. Przyjrzyjmy się teraz przykładowi użytemu w sekcji powyżej, aby dowiedzieć się, jak osiągnąć dozwolony limit 10 żądań dla każdego z docelowych punktów końcowych.
    • Zdefiniuj osobne zasady dotyczące limitów, po jednej dla docelowych punktów końcowych „Target-US” i „Target-EU”.

      Zasady dotyczące limitu 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>
      

      Zasady dotyczące limitów w docelowym punkcie końcowym „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 odpowiednich zasad dotyczących 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>
      
    • W docelowych punktach końcowych „Target-US” i „Target-EU” używamy oddzielnych zasad dotyczących limitów, więc zachowamy oddzielny licznik. Dzięki temu uzyskujemy dozwolony limit 10 żądań do interfejsu API na minutę dla każdego z docelowych punktów końcowych.
  • Użyj elementów <Class> lub <Identifier>, aby utrzymywać wiele liczników unikalnych użytkowników.