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

您正在查看 ApigeeApigee Hybrid 說明文件。
查看 Apigee Edge 說明文件。

Apigee 可讓您使用配額政策,設定在特定時間內允許傳送至 API Proxy 的要求數。

反模式

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

  • 在 API Proxy 的相同或不同資料流
  • 在 API Proxy 的不同目標端點

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

讓我們用以下範例來說明配額政策的運作方式。

API Proxy

假設有一個名為「TestTargetServerQuota」的 API Proxy,而這個 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> 元素來維護多個不重複的計數器。