反模式:重複使用配額政策

您正在查看 Apigee Edge 說明文件。
查看 Apigee X 說明文件
資訊

Apigee Edge 可讓您使用配額政策,設定在特定時間內允許對 API Proxy 發出的要求數量。

反模式

如果重複使用配額政策,則每次執行該配額政策時 (無論用於何處),配額計數器都會遞減。也就是說,如果在下列位置重複使用配額政策:

  • 在 API Proxy 的相同流程或不同流程中
  • 在 API Proxy 的不同目標端點中

那麼每次執行配額政策時,配額計數器都會遞減,而且在指定的時間間隔內,最終都會比預期更早收到配額違規錯誤。

讓我們用以下範例說明運作方式。

API Proxy

假設有一個名為「TestTargetServerQuota」的 API Proxy,並根據資源路徑將流量轉送至兩個不同的目標伺服器。我們希望將每個目標伺服器的 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」的預流中使用配額政策「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 Proxy 總共收到 10 個 API 要求:

資源路徑 /target-us /target-eu 全部
# 個要求 4 6 10

稍後 (假設 32 秒後),我們收到第 11 個 API 要求,其資源路徑為 /target-us

如果按照允許的配額計算,目標端點 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 Proxy 中分別使用不同的配額政策,確保您能隨時取得允許的 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> 元素來維護多個不重複的計數器。