Antipatrón: Vuelve a usar una política de cuotas

Estás viendo la documentación de Apigee y Apigee Hybrid.
Consulta la documentación de Apigee Edge.

Apigee proporciona la capacidad de configurar la cantidad de solicitudes permitidas para un proxy de API durante un período específico mediante la política de cuotas.

Antipatrón

Si se vuelve a usar una política de cuotas, el contador de cuotas se reducirá cada vez que se ejecute la política de cuotas, sin importar dónde se use. Es decir, si se vuelve a usar una política de cuotas en las siguientes situaciones:

  • En el mismo flujo o en diferentes flujos de un proxy de API
  • En extremos de destino diferentes de un proxy de API

Luego, el contador de cuotas se reduce cada vez que se ejecuta y dará como resultado errores de incumplimiento de cuota mucho antes de lo esperado para el intervalo especificado.

Usemos el siguiente ejemplo para explicar cómo funciona.

Proxy de API

Supongamos que tenemos un proxy de API que se llama "TestTargetServerQuota" y que enruta el tráfico a dos servidores de destino diferentes según la ruta de acceso al recurso. Queremos restringir el tráfico de la API a 10 solicitudes por minuto para cada uno de los servidores de destino. En esta tabla, se describe el ejemplo:

Ruta de acceso al recurso Servidor de destino Cuota
/target-us target-US.somedomain.com 10 solicitudes por minuto
/target-eu target-EU.somedomain.com 10 solicitudes por minuto

Política de cuotas

Debido a que la cuota de tráfico es la misma para ambos servidores de destino, definimos una sola política de cuotas llamada "Quota-Minute-Target-Server", como se muestra a continuación:

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

Extremos de destino

Usemos la política de cuotas "Quota-Minute-Target-Server" en el flujo previo del extremo de destino "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>

Y reutilicemos la misma política de cuotas, "Quota-Minute-Target-Server", en el flujo previo del otro extremo de destino, "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>

Patrón de tráfico entrante

Supongamos que obtenemos un total de 10 solicitudes a la API para este proxy de API dentro de los primeros 30 segundos en el siguiente patrón:

Ruta de acceso al recurso /target-us /target-eu Todos
# Solicitudes 4 6 10

Un poco después, obtenemos la solicitud a la API n.º 11 con la ruta de acceso del recurso como /target-us, digamos después de 32 segundos.

Esperamos que la solicitud se realice correctamente, siempre y cuando haya 6 solicitudes a la API para el extremo de destino target-us, según la cuota permitida.

Sin embargo, en realidad, obtenemos un Quota violation error.

Motivo: Debido a que usamos la misma política de cuotas en ambos extremos de destino, un único contador de cuotas se usa para realizar un seguimiento de las solicitudes a la API que llegan a ambos extremos de destino. Por lo tanto, agotamos la cuota de 10 solicitudes por minuto de forma colectiva en lugar de hacerlo en el extremo de destino individual.

Impacto

Este antipatrón puede dar como resultado una falta de coincidencia fundamental de las expectativas, lo que genera una percepción de que los límites de la cuota se agotaron antes de tiempo.

Práctica recomendada

  • Usa los elementos <Class> o <Identifier> para garantizar que varios contadores únicos se mantienen mediante la definición de una sola política de cuotas. Volvamos a definir la política de cuotas "Quota-Minute-Target-Server", que explicamos en la sección anterior, mediante el uso del encabezado target_id como el <Identifier>, como se muestra a continuación:
    <!-- /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>
    • Seguiremos usando esta política de cuotas en los extremos de destino "Target-US" y "Target-EU" como antes.
    • Ahora, supongamos que si el encabezado target_id tiene un valor “US”, entonces las solicitudes se enrutarán al extremo de destino “Target-US”.
    • Del mismo modo, si el encabezado target_id tiene un valor "EU", las solicitudes se enrutan al extremo de destino "Target-EU".
    • Entonces, incluso si usamos la misma política de cuotas en ambos extremos de destino, los contadores de cuotas independientes se mantienen según el valor <Identifier>.
    • Por lo tanto, si usamos el elemento <Identifier>, podemos garantizar que cada extremo de destino obtiene la cuota permitida de 10 solicitudes.
  • Usa políticas de cuotas independientes en cada flujo, extremo de destino o proxy de API para garantizar que siempre obtengas el recuento permitido de solicitudes a la API. Ahora, usemos el mismo ejemplo de la sección anterior para ver cómo podemos lograr la cuota permitida de 10 solicitudes para cada extremo de destino.
    • Define una política de cuotas distinta, una para cada uno de los extremos de destino "Target-US" y "Target-EU"

      Política de cuotas para el extremo de destino “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>

      Política de cuotas para el extremo de destino “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>
    • Usa la política de cuotas correspondiente en la definición de los extremos de destino como se muestra a continuación:

      Extremo de destino "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>

      Extremo de destino "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>
    • Debido a que usamos una política de cuotas independiente en los extremos de destino "Target-US" y "Target-EU", se mantendrá un contador independiente. Esto garantiza que se obtendrá la cuota permitida de 10 solicitudes a la API por minuto para cada uno de los extremos de destino.
  • Usa los elementos <Class> o <Identifier> para garantizar que se mantienen varios contadores únicos.