アンチパターン: 割り当てポリシーを再利用する

現在、ApigeeApigee ハイブリッドのドキュメントを表示しています。
Apigee Edge のドキュメントを表示する。

Apigee では、割り当てポリシーを使用して、一定期間内に API プロキシへ送信可能なリクエスト件数を構成できます。

アンチパターン

割り当てポリシーを再利用する場合は、それがどこで利用されるかに関係なく、割り当てポリシーの実行のたびに割り当てカウンタが減少します。たとえば、割り当てポリシーが以下の場所で再利用されたとします。

  • 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-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」のプリフローで割り当てポリシー「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-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 プロキシに対する API リクエストを合計 10 件受け取ったとします。

リソースパス /target-us /target-eu すべて
リクエスト件数 4 6 10

少し後に、/target-us のリソースパスで 11 件目の API リクエストを受け取ります。たとえばそれを 32 秒後だとします。

許可された割り当てに基づくと、ターゲット エンドポイント target-us にはまだ 6 件の API リクエストが残っていると推測されるため、リクエストは正常に処理されると予測します。

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

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

影響

このアンチパターンにより、予測とまったく一致しない状況が生じるため、割り当て上限を早めに使い切ったと感じることになります。

ベスト プラクティス

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

      ターゲット エンドポイント「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」で個別の割り当てポリシーを使用しているため、個別のカウンタが維持されます。これにより、ターゲット エンドポイントごとに 1 分あたり 10 件の API リクエストの割り当てを確実に受け取ることができます。
  • <Class> 要素または <Identifier> 要素を使用すると、それぞれ異なるカウンタを複数維持できます。