Chống lỗi: Sử dụng lại chính sách Hạn mức

Bạn đang xem tài liệu về Apigee Edge.
Truy cập vào tài liệu Apigee X.
thông tin

Apigee Edge cung cấp khả năng định cấu hình số lượng yêu cầu được phép cho một API Proxy trong một khoảng thời gian cụ thể bằng cách sử dụng Chính sách hạn mức.

Antipattern

Nếu một Chính sách hạn mức được dùng lại, thì bộ đếm hạn mức sẽ giảm mỗi khi Chính sách hạn mức được thực thi, bất kể chính sách đó được dùng ở đâu. Tức là nếu một chính sách Hạn mức được dùng lại:

  • Trong cùng một luồng hoặc các luồng khác nhau của một API Proxy
  • Trong các điểm cuối mục tiêu khác nhau của một API Proxy

Sau đó, bộ đếm hạn mức sẽ giảm mỗi khi được thực thi và chúng ta sẽ gặp phải lỗi Vi phạm hạn mức sớm hơn nhiều so với dự kiến trong khoảng thời gian đã chỉ định.

Hãy sử dụng ví dụ sau để giải thích cách hoạt động của tính năng này.

API Proxy

Giả sử chúng ta có một API Proxy có tên là "TestTargetServerQuota", định tuyến lưu lượng truy cập đến 2 máy chủ đích khác nhau dựa trên đường dẫn tài nguyên. Chúng tôi muốn hạn chế lưu lượng truy cập API ở mức 10 yêu cầu mỗi phút cho từng máy chủ mục tiêu này. Sau đây là bảng mô tả tình huống này:

Đường dẫn đến tài nguyên Máy chủ đích Hạn mức
/target-us target-US.somedomain.com 10 yêu cầu mỗi phút
/target-eu target-EU.somedomain.com 10 yêu cầu mỗi phút

Chính sách hạn mức

Vì hạn mức lưu lượng truy cập cho cả hai máy chủ đích đều giống nhau, nên chúng ta sẽ xác định một chính sách Hạn mức duy nhất có tên là "Quota-Minute-Target-Server" như minh hoạ bên dưới:

<!-- /antipatterns/examples/1-8.xml -->
<Quota name="Quota-Minute-Target-Server">
  <Interval>1</Interval>
  <TimeUnit>minute</TimeUnit>
  <Distributed>true</Distributed>
  <Allow count="10"/>
</Quota>

Điểm cuối mục tiêu

Hãy sử dụng chính sách Hạn mức "Quota-Minute-Target-Server" trong luồng trước của điểm cuối mục tiêu "Target-US":

<!-- /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>

Và sử dụng lại chính sách Hạn mức "Quota-Minute-Target-Server" trong luồng trước của điểm cuối mục tiêu khác "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>

Mẫu lưu lượng truy cập đến

Giả sử chúng ta nhận được tổng cộng 10 yêu cầu API cho API Proxy này trong 30 giây đầu tiên theo mẫu sau:

Đường dẫn đến tài nguyên /target-us /target-eu Tất cả
# Requests 4 6 10

Một lúc sau, chúng ta nhận được yêu cầu API thứ 11 với đường dẫn tài nguyên là /target-us, giả sử sau 32 giây.

Chúng tôi dự kiến yêu cầu sẽ được thực hiện thành công, giả sử chúng tôi vẫn còn 6 yêu cầu API cho điểm cuối mục tiêu target-us theo hạn mức được phép.

Tuy nhiên, trên thực tế, chúng ta sẽ nhận được một Quota violation error.

Lý do: Vì chúng tôi đang sử dụng cùng một chính sách về hạn mức ở cả hai điểm cuối mục tiêu, nên một bộ đếm hạn mức duy nhất được dùng để theo dõi các yêu cầu API gửi đến cả hai điểm cuối mục tiêu. Do đó, chúng ta sẽ sử dụng hết hạn mức 10 yêu cầu mỗi phút cho tất cả các yêu cầu chứ không phải cho từng điểm cuối mục tiêu riêng lẻ.

Tác động

Mô hình chống lại này có thể dẫn đến sự không phù hợp cơ bản về kỳ vọng, dẫn đến nhận thức rằng hạn mức đã hết trước thời hạn.

Phương pháp hay nhất

  • Sử dụng các phần tử <Class> hoặc <Identifier> để đảm bảo duy trì nhiều bộ đếm riêng biệt bằng cách xác định một Chính sách hạn mức duy nhất. Hãy xác định lại chính sách Hạn mức "Quota-Minute-Target-Server" mà chúng ta vừa giải thích trong phần trước bằng cách sử dụng tiêu đề target_id làm <Identifier> như minh hoạ bên dưới:
    <!-- /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>
    • Chúng tôi sẽ tiếp tục sử dụng Chính sách về hạn mức này ở cả hai điểm cuối mục tiêu "Target-US" và "Target-EU" như trước đây.
    • Giả sử tiêu đề target_id có giá trị "US", thì các yêu cầu sẽ được định tuyến đến điểm cuối mục tiêu "Target-US".
    • Tương tự, nếu tiêu đề target_id có giá trị "EU", thì các yêu cầu sẽ được định tuyến đến điểm cuối mục tiêu "Target-EU".
    • Vì vậy, ngay cả khi chúng ta sử dụng cùng một chính sách Hạn mức ở cả hai điểm cuối mục tiêu, các bộ đếm hạn mức riêng biệt vẫn được duy trì dựa trên giá trị <Identifier>.
    • Do đó, bằng cách sử dụng phần tử <Identifier>, chúng ta có thể đảm bảo rằng mỗi điểm cuối mục tiêu đều nhận được hạn mức cho phép là 10 yêu cầu.
  • Sử dụng chính sách Hạn mức riêng biệt trong mỗi luồng/điểm cuối mục tiêu/API Proxy để đảm bảo bạn luôn nhận được số lượng yêu cầu API được phép. Bây giờ, hãy xem xét ví dụ tương tự được dùng trong phần trên để xem cách chúng ta có thể đạt được hạn mức cho phép là 10 yêu cầu cho mỗi điểm cuối mục tiêu.
    • Xác định một chính sách Hạn mức riêng, mỗi chính sách cho các điểm cuối mục tiêu "Target-US" và "Target-EU"

      Chính sách hạn mức cho Điểm cuối mục tiêu "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>

      Chính sách hạn mức cho Điểm cuối mục tiêu "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>
    • Sử dụng chính sách hạn mức tương ứng trong định nghĩa của các điểm cuối mục tiêu như minh hoạ dưới đây:

      Điểm cuối mục tiêu "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>

      Điểm cuối mục tiêu "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>
    • Vì chúng tôi đang sử dụng chính sách Hạn mức riêng biệt trong các điểm cuối mục tiêu "Target-US" và "Target-EU", nên chúng tôi sẽ duy trì một bộ đếm riêng biệt. Điều này đảm bảo rằng chúng ta nhận được hạn mức cho phép là 10 yêu cầu API mỗi phút cho từng điểm cuối mục tiêu.
  • Sử dụng các phần tử <Class> hoặc <Identifier> để đảm bảo duy trì nhiều bộ đếm riêng biệt.