反模式:重复使用配额政策

<ph type="x-smartling-placeholder"></ph> 您正在查看 Apigee Edge 文档。
转到 Apigee X 文档
信息

Apigee Edge 提供了为 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>

目标端点

我们在目标端点的前流中使用配额政策“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”:

<!-- /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 代理的 以下格式:

资源路径 /target-us /target-eu 总计
请求数 4 6 10

稍后,我们收到第 11 个 API 请求,其资源路径为 /target-us, 设为 32 秒后展示

我们认为,根据允许的配额,目标端点 target-us 还可以接受 6 个 API 请求,因此该请求能够成功通过。

但实际上,我们得到了 Quota violation error

原因:因为我们在两个目标端点中使用同一配额政策,因此系统使用单个配额计数器跟踪到达两个目标端点的 API 请求。因此,我们用光了每分钟总共(而不是单个目标端点)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_id 的值为“US”,则请求将路由到 目标端点“Target-US”
    • 同样,如果标头 target_id 的值为“EU”,则请求会路由到目标 端点“Target-EU”
    • 因此,即使我们在两个目标端点中使用同一配额政策,系统也会根据 <Identifier> 值维护单独的配额计数器。
    • 因此,通过使用 <Identifier> 元素,我们可以确保每个目标端点都获得 10 个请求的允许配额。
  • 在每个流/目标端点/API 代理中使用单独的配额政策,以确保始终获得允许的 API 请求数量。下面,让我们来看看 请参阅上一节,了解如何实现每个目标的允许配额(10 次请求) 端点。
    • 定义单独的配额政策,目标端点“Target-US”和 “目标-欧盟”

      目标端点“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> 元素确保维护多个不同的计数器。