Anti-Pattern: Kontingentrichtlinie wiederverwenden

Sie sehen die Dokumentation zu Apigee Edge.
Zur Apigee X-Dokumentation
weitere Informationen

Apigee Edge bietet die Möglichkeit, die Anzahl der zulässigen Anfragen für einen API-Proxy für einen bestimmten Zeitraum mithilfe der Kontingentrichtlinie zu konfigurieren.

Anti-Pattern

Beim Wiederverwenden einer Kontingentrichtlinie wird der Kontingentzähler bei jeder Ausführung der Kontingentrichtlinie verringert, unabhängig davon, wo Kontingent verbraucht wird. Wird also eine Kontingentrichtlinie wiederverwendet:

  • Innerhalb desselben Ablaufs oder verschiedener Abläufe eines API-Proxys
  • In verschiedenen Zielendpunkten eines API-Proxys

wird der Kontingentzähler bei jeder Ausführung verringert und es kommt viel früher als für die bestimmte Zeitspanne angenommen zu Fehlern infolge eines Kontingentverstoßes.

Im folgenden Beispiel wird die Funktionsweise näher erläutert.

API-Proxy

Nehmen wir an, wir haben einen API-Proxy namens „TestTargetServerQuota“, der den Traffic basierend auf dem Ressourcenpfad an zwei verschiedene Zielserver weiterleitet. Außerdem möchten wir den API-Traffic auf 10 Anfragen pro Minute pro Zielserver beschränken. Hier ist die Tabelle, die dieses Szenario darstellt:

Ressourcenpfad Zielserver Kontingent
/target-us target-US.somedomain.com 10 Anfragen pro Minute
/target-eu target-EU.somedomain.com 10 Anfragen pro Minute

Kontingentrichtlinie

Da das Traffic-Kontingent für beide Zielserver gleich ist, definieren wir eine einzelne Kontingentrichtlinie mit dem Namen „Quota-Minute-Target-Server“, wie unten dargestellt:

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

Zielendpunkte

Nehmen wir die Kontingentrichtlinie „Quota-Minute-Target-Server“ im Preflow des Zielendpunkts „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>

Verwenden Sie dieselbe Kontingentrichtlinie „Quota-Minute-Target-Server“ im Preflow des anderen Zielendpunkts „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>

Muster für eingehenden Traffic

Angenommen, wir erhalten innerhalb der ersten 30 Sekunden insgesamt 10 API-Anfragen für diesen API-Proxy im folgenden Muster:

Ressourcenpfad /target-us /target-eu Alle
Anzahl der Anfragen 4 6 10

Etwas später erhalten wir die elfte API-Anfrage mit dem Ressourcenpfad als /target-us, z. B. nach 32 Sekunden.

Wir gehen unter der Annahme, dass wir nach zulässigem Kontingent noch sechs API-Anfragen für den Zielendpunkt target-us haben, davon aus, dass die Anfrage erfolgreich ausgeführt wird.

Tatsächlich erhalten wir jedoch diesen Fehler: Quota violation error.

Grund: Weil wir für beide Zielendpunkte dieselbe Kontingentrichtlinie verwenden, dient zum Erfassen der API-Anfragen an beiden Zielendpunkten ein einzelner Kontingentzähler. Entsprechend erschöpfen wir das Kontingent von 10 Anfragen pro Minute aggregiert und nicht für den einzelnen Zielendpunkt aus.

Auswirkungen

Dieses Anti-Pattern kann zu einer bedeutenden Abweichung führen und zu der Annahme, dass die Kontingentlimits zu schnell aufgebraucht wurden.

Best Practice

  • Verwenden Sie das Element <Class> oder <Identifier>, um mehrere eindeutige Zähler durch die Definition einer einzigen Kontingentrichtlinie zu verwalten. Definieren wir die im vorherigen Abschnitt erläuterte Kontingentrichtlinie „Quota-Minute-Target-Server“ neu, indem wir wie unten gezeigt den Header target_id als <Identifier> verwenden:
    <!-- /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>
    
    • Wie zuvor wird diese Kontingentrichtlinie sowohl für die Zielendpunkte „Target-US“ als auch „Target-EU“ verwendet.
    • Wenn der Header target_id den Wert „US“ hat, werden die Anfragen an den Zielendpunkt „Target-US“ weitergeleitet.
    • Wenn der Header target_id den Wert „EU“ hat, werden die Anfragen an den Zielendpunkt „Target-EU“ weitergeleitet.
    • Selbst wenn wir für beide Zielendpunkte dieselbe Kontingentrichtlinie verwenden, werden also separate Kontingentzähler auf Grundlage des Werts <Identifier> verwaltet.
    • Daher können wir mit dem Element <Identifier> dafür sorgen, dass jeder der Zielendpunkte das zulässige Kontingent von 10 Anfragen erhält.
  • Verwenden Sie in jedem der Abläufe/Zielendpunkte/API-Proxys separate Kontingentrichtlinien, um immer die zulässige Anzahl von API-Anfragen zu erhalten. Sehen wir uns nun das im obigen Abschnitt verwendete Beispiel an, um zu sehen, wie wir das zulässige Kontingent von 10 Anfragen für jeden der Zielendpunkte erreichen können.
    • Definieren Sie eine separate Kontingentrichtlinie, jeweils eine für die Zielendpunkte „Target-US“ und „Target-EU“.

      Kontingentrichtlinie für den Zielendpunkt „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>
      

      Kontingentrichtlinie für den Zielendpunkt „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>
      
    • Verwenden Sie die entsprechende Kontingentrichtlinie in der Definition der Zielendpunkte, wie unten dargestellt:

      Zielendpunkt „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>
      

      Zielendpunkt „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>
      
    • Da wir separate Kontingentrichtlinien für die Zielendpunkte „Target-US“ und „Target-EU“ verwenden, wird ein separater Zähler verwaltet. Dadurch wird sichergestellt, dass wir für jeden der Zielendpunkte das zulässige Kontingent von 10 API-Anfragen pro Minute erhalten.
  • Verwenden Sie das Element <Class> oder <Identifier>, um mehrere eindeutige Zähler zu verwalten.