עיצוב נגדי: שימוש חוזר במדיניות מכסה

מוצג המסמך של Apigee Edge.
עוברים אל מסמכי תיעוד של Apigee X.
מידע

Apigee Edge מספקת את היכולת להגדיר את מספר הבקשות המותרות לשרת Proxy ל-API עבור תקופת זמן ספציפית באמצעות המדיניות בנושא Quota.

נגד דוגמת עיצוב

אם משתמשים שוב במדיניות מכסה, מונה המכסה מצטמצם בכל פעם מדיניות המכסה מופעלת ללא קשר למיקום שבו משתמשים בה. כלומר, אם מדיניות מכסה בשימוש חוזר:

  • באותו תהליך או בתהליכים שונים של שרת proxy ל-API
  • בנקודות קצה שונות של יעד של שרת Proxy ל-API

לאחר מכן מונה המכסה יקטן בכל פעם שהיא תבוצע, ובסופו של דבר נצליח לקבל שגיאות שקשורות להפרה של המכסות הרבה יותר מוקדמות מהמצופה בפרק הזמן שצוין.

נבחן את הדוגמה הבאה כדי להסביר איך זה עובד.

שרת proxy ל-API

נניח שיש לנו שרת Proxy ל-API בשם "TestTargetServerQuota", שמנתב את התנועה שרתי יעד שונים בהתאם לנתיב המשאב. ואנחנו רוצים להגביל את התנועה דרך ה-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 בתהליך ההגדרה מראש של נקודת הקצה של היעד. '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>

ועושים שימוש חוזר באותה מדיניות מכסה 'Quota-Minute-Target-Server' בהגדרה של היעד השני גם את נקודת הקצה '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>

דפוס תנועה נכנסת

נניח שאנחנו מקבלים סה"כ 10 בקשות API לשרת ה-proxy הזה ל-API ב-30 השניות הראשונות של את התבנית הבאה:

נתיב המשאב /target-us /target-eu הכול
מס' בקשות 4 6 10

קצת מאוחר יותר אנחנו מקבלים את בקשת ה-API ה-11 עם נתיב המשאב: /target-us, נניח אחרי 32 שניות.

אנחנו מצפים שהבקשה תתבצע בהצלחה, בהנחה שעדיין יש לנו 6 בקשות API נקודת הקצה (endpoint) target-us של היעד, בהתאם למכסה המותרת.

אבל בפועל, אנחנו מקבלים Quota violation error.

הסיבה: מכיוון שאנחנו משתמשים באותה מדיניות מכסה בשתי נקודות הקצה של היעד, מונה מכסה יחיד משמש למעקב אחרי בקשות ה-API שמגיעות לנקודות הקצה (endpoints) של היעד. לכן אנחנו למצות את המכסה של 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> אפשר לוודא שכל נקודות הקצה (endpoints) של היעד מקבלים את המכסה המותרת של 10 בקשות.
  • להשתמש במדיניות מכסה נפרדת בכל תהליכים, נקודות הקצה ביעד או שרתי proxy ל-API, כדי לוודא לקבל תמיד את המספר המותר של בקשות API. עכשיו נסתכל על אותה הדוגמה שבה נעשה שימוש בקטע שלמעלה כדי לבדוק איך אפשר להגיע למכסה המותרת של 10 בקשות לכל אחד מהיעדים נקודות קצה (endpoints).
    • מגדירים מדיניות מכסות נפרדת, אחת לכל נקודות הקצה של היעד '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>
      

      מדיניות המכסות של נקודת קצה מסוג יעד 'יעד באיחוד האירופי':

      <!-- /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>
      
    • משתמשים במדיניות המכסה המתאימה בהגדרה של נקודות הקצה כיעד, כפי שמוצג בהמשך:

      נקודת קצה (endpoint) יעד '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>
      

      נקודת קצה (endpoint) יעד '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> כדי לוודא מנוהלים מוניים ייחודיים רבים.