안티패턴: 할당량 정책 재사용

ApigeeApigee Hybrid 문서입니다.
Apigee Edge 문서 보기

Apigee에서는 할당량 정책을 사용하여 특정 기간 동안 API 프록시에 허용되는 요청 수를 구성할 수 있습니다.

안티패턴

할당량 정책이 재사용되면 할당량 정책이 사용되는 위치와 상관없이 실행될 때마다 할당량 카운터가 줄어듭니다. 즉, 할당량 정책이 다음과 같이 재사용되는 경우입니다.

  • API 프록시의 동일한 흐름 또는 다른 흐름 내에서
  • API 프록시의 다른 대상 엔드포인트에서

그러면 할당량 카운터가 실행될 때마다 감소하여 결국 지정된 시간 간격에 대해 예상한 것보다 훨씬 빨리 할당량 초과 오류가 발생합니다.

다음 예시를 통해 작동 방식을 설명해 보겠습니다.

API 프록시

리소스 경로에 따라 트래픽을 서로 다른 두 개의 대상 서버로 라우팅하는 'TestTargetServerQuota'라는 API 프록시가 있다고 가정해 보겠습니다. 그리고 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>

대상 엔드포인트

대상 엔드포인트 'Target-US'의 preflow에서 할당량 정책 '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>

다른 대상 엔드포인트 'Target-EU'의 preflow에서도 동일한 할당량 정책 'Quota-Minute-Target-Server'를 재사용합니다.

<!-- /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초 후에 리소스 경로가 /target-us인 11번째 API 요청을 받습니다.

대상 엔드포인트 target-us에 여전히 6개의 API 요청이 허용되는 할당량으로 남아있다고 가정하면 요청이 성공적으로 처리될 것으로 예상됩니다.

하지만 실제로는 Quota violation error가 발생합니다.

이유: 두 개의 대상 엔드포인트에서 동일한 할당량 정책을 사용하므로 두 개의 대상 엔드포인트에 모두 적용되는 API 요청을 추적하는 데 단일 할당량 카운터가 사용됩니다. 따라서 개별 대상 엔드포인트가 아니라 분당 요청 10개의 할당량이 소진됩니다.

영향

이러한 안티패턴은 근본적인 기대 수준의 불일치를 초래하여 할당량 한도가 조기에 소진되었다고 인식하게 만듭니다.

권장사항

  • <Class> 또는 <Identifier> 요소를 사용해서 단일 할당량 정책을 정의하여 여러 개의 고유한 카운터가 유지되도록 합니다. 아래와 같이 target_id 헤더를 <Identifier>로 사용하여 이전 섹션에서 설명한 할당량 정책 'Quota-Minute-Target-Server'를 다시 정의하겠습니다.
    <!-- /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> 요소를 사용하여 여러 개의 고유한 카운터를 유지합니다.