アンチパターン: Quota ポリシーの再利用

Apigee Edge の Quota ポリシーを使用すると、一定期間内に API プロキシに送信できるリクエストの数を構成できます。

アンチパターン

Quota ポリシーは再利用されると、使用される場所に関係なく、Quota ポリシーが実行されるたびに割り当てカウンタが減少します。つまり、Quota ポリシーが以下のどちらで再利用された場合でも減少します。

  • API プロキシの同じフロー内または異なるフロー内
  • API プロキシの異なるターゲット エンドポイント

実行されるたびに割り当てカウンタが減少し、指定された時間間隔で予想されるよりもはるかに早く割り当て違反エラーが発生します。

次の例を使用して、これがどのように機能するかを説明しましょう。

API プロキシ

「TestTargetServerQuota」という名前の API プロキシがあるとします。これはリソースパスに基づいて 2 つの異なるターゲット サーバーにトラフィックをルーティングします。また、これらの各ターゲット サーバーの API トラフィックを 1 分あたり 10 リクエストに制限します。このシナリオをテーブルにまとめると、次のようになります。

リソースパス ターゲット サーバー 割り当て
/target-us target-US.somedomain.com 1 分あたり 10 リクエスト
/target-eu target-EU.somedomain.com 1 分あたり 10 リクエスト

Quota ポリシー

トラフィック割り当ては両方のターゲット サーバーで同じであるため、以下に示すように「Quota-Minute-Target-Server」という名前の単一の Quota ポリシーを定義します。

<!-- /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」のプリフローで Quota ポリシー「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」のプリフローでも同じ Quota ポリシー「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

少し後、/target-us のリソースパスで 11 個目の API リクエストを受け取ります。32 秒後だとしましょう。

許可された割り当てに基づくと、ターゲット エンドポイント target-us ではまだ 6 個の API リクエストを受け取れるはずなので、リクエストは正常に処理されると想定します。

しかし実際には、Quota violation error を受け取ります。

理由: 両方のターゲット エンドポイントで同一の Quota ポリシーを使用しているため、両方のターゲット エンドポイントに到達する API リクエストを追跡するために、単一の割り当てカウンタを使用しています。そのため、それぞれのターゲット エンドポイントではなく、両方のターゲット ポイントで合計して 1 分あたり 10 のリクエスト割り当てを使い切っています。

影響

このアンチパターンは、根本的に期待と一致しない状況を作り出し、割り当て上限を早めに使い切ったと感じさせることになります。

ベスト プラクティス

  • <Class> または <Identifier> 要素を使用して、単一の Quota ポリシーを定義することにより、複数の一意のカウンタが維持されるようにします。前のセクションで説明した Quota ポリシー「Quota-Minute-Target-Server」を再定義しましょう。以下に示すようにヘッダー target_id<Identifier> として使用します。
    <!-- /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」の両方でこの Quota ポリシーを引き続き使用します。
    • ヘッダー target_id の値が「US」の場合、リクエストはターゲット エンドポイント「Target-US」にルーティングされます。
    • 同様に、ヘッダー target_id の値が「EU」の場合、リクエストはターゲット エンドポイント「Target-EU」にルーティングされます。
    • そのため、両方のターゲット エンドポイントで同じ Quota ポリシーを使用しても、<Identifier> 値に基づいて個別の割り当てカウンタが維持されます。
    • したがって、<Identifier> 要素を使用することにより、ターゲット エンドポイントのそれぞれが許可された 10 のリクエストの割り当てを確実に受け取れるようになります。
  • 各フロー / ターゲット エンドポイント / API プロキシで個別の Quota ポリシーを使用して、許可された数の API リクエストを常に受け取れるようにします。ここで、上記のセクションと同じ例を使用して、ターゲット エンドポイントごとに許可された 10 のリクエスト割り当てを達成する方法を見てみましょう。
    • ターゲット エンドポイント「Target-US」と「Target-EU」に 1 つずつ、個別の Quota ポリシーを定義します。

      ターゲット エンドポイント「Target-US」の Quota ポリシー:

      <!-- /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」の Quota ポリシー:

      <!-- /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>
          
    • 以下に示すように、ターゲット エンドポイントの定義でそれぞれの Quota ポリシーを使用します。

      ターゲット エンドポイント「Target-EU」:

      <!-- /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-us.somedomain.com</URL>
            </HTTPTargetConnection>
          </TargetEndpoint>
          
    • ターゲット エンドポイント「Target-US」と「Target-EU」で個別の Quota ポリシーを使用しているため、個別のカウンタが維持されます。これにより、それぞれのターゲット エンドポイントで 1 分あたり 10 の API リクエストという許可された割り当てを受け取れます。
  • <Class> または <Identifier> 要素を使用して、複数の一意のカウンタが維持されるようにします。