אנטי-תבנית: שימוש בפונקציה waitForComplete()‎ בקוד JavaScript

הדף הזה רלוונטי ל-Apigee ול-Apigee Hybrid.

לעיון במסמכי התיעוד של Apigee Edge

מדיניות JavaScript מאפשרת להוסיף קוד בהתאמה אישית שמופעל בהקשר של תהליך proxy ל-API. לדוגמה, אפשר להשתמש בקוד המותאם אישית במדיניות JavaScript כדי:

  • קבלת משתני זרימה והגדרתם
  • הפעלת לוגיקה מותאמת אישית וביצוע טיפול בשגיאות
  • חילוץ נתונים מבקשות או מתשובות
  • עריכה דינמית של כתובת ה-URL של היעד בקצה העורפי
  • הוספה או הסרה דינמית של כותרות מבקשה או מתגובה
  • ניתוח תגובת JSON

צד הלקוח ב-HTTP

תכונה חשובה של מדיניות Javascript היא לקוח ה-HTTP. אפשר להשתמש בלקוח ה-HTTP (או באובייקט httpClient) כדי לבצע קריאה אחת או יותר לשירותי קצה עורפי או לשירותים חיצוניים. לקוח ה-HTTP שימושי במיוחד כשצריך לבצע קריאות למספר שירותים חיצוניים ולשלב את התשובות ב-API יחיד.

קוד JavaScript לדוגמה שיוצר קריאה ל-backend עם אובייקט httpClient

var headers = {'X-SOME-HEADER' : 'some value' };
var myRequest = new Request("http://www.example.com","GET",headers);
var exchange = httpClient.send(myRequest);

אובייקט httpClient חושף שתי שיטות get ו-send (send משמש בקוד לדוגמה שלמעלה) כדי ליצור בקשות HTTP. שתי השיטות הן אסינכרוניות ומחזירות אובייקט exchange לפני שהבקשה בפועל של HTTP מסתיימת.

יכול להיות שיעברו כמה שניות או כמה דקות עד שהבקשות מסוג HTTP יתקבלו. אחרי ששולחים בקשת HTTP, חשוב לדעת מתי היא מסתיימת כדי שאפשר יהיה לעבד את התגובה לבקשה. אחת הדרכים הנפוצות ביותר לקבוע מתי בקשת ה-HTTP הושלמה היא הפעלת השיטה waitForComplete() של האובייקט exchange.

waitForComplete()

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

קוד JavaScript לדוגמה עם waitForComplete()‎

var headers = {'X-SOME-HEADER' : 'some value' };
var myRequest = new Request("http://www.example.com","GET",headers);
var exchange = httpClient.send(myRequest);
// Wait for the asynchronous GET request to finish
exchange.waitForComplete();

// Get and Process the response
if (exchange.isSuccess()) {
    var responseObj = exchange.getResponse().content.asJSON;
    return responseObj.access_token;
} else if (exchange.isError()) {
    throw new Error(exchange.getError());
}

תבנית אנטי

שימוש ב-waitForComplete() אחרי שליחת בקשת HTTP בקוד JavaScript ישפיע על הביצועים.

נבחן את קוד ה-JavaScript הבא שקורא ל-waitForComplete() אחרי שליחת בקשת HTTP.

קוד לדוגמה sample.js

// Send the HTTP request
var exchangeObj = httpClient.get("http://example.com");
// Wait until the request is completed
exchangeObj.waitForComplete();
// Check if the request was successful
if (exchangeObj.isSuccess())  {

    response = exchangeObj.getResponse();
    context.setVariable('example.status', response.status);
} else {
   error = exchangeObj.getError();
   context.setVariable('example.error', 'Woops: ' + error);
}

בדוגמה הזו:

  1. קוד ה-JavaScript שולח בקשת HTTP ל-API של ה-Backend.
  2. לאחר מכן, הפונקציה קוראת ל-waitForComplete() כדי להשהות את הביצוע עד לסיום הבקשה.

    waitForComplete() API גורם לחסימת השרשור שמבצע את קוד ה-JavaScript עד שהקצה העורפי מסיים את עיבוד הבקשה ומגיב.

קיימת מגבלה עליונה על מספר השרשורים (30%) שיכולים להריץ קוד JavaScript בו-זמנית במעבד הודעות בכל זמן נתון. אחרי שמגיעים למגבלה הזו, לא יהיו יותר שרשורים זמינים להרצת קוד ה-JavaScript. לכן, אם יש יותר מדי בקשות בו-זמניות שמבצעות את waitForComplete() API בקוד JavaScript, הבקשות הבאות ייכשלו עם הודעת השגיאה 500 Internal Server Error ו-Timed out עוד לפני שפג הזמן הקצוב לתפוגה של מדיניות JavaScript.

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

השפעה

  1. בקשות ה-API ייכשלו עם השגיאה 500 Internal Server Error ועם הודעת השגיאה Timed out אם מספר הבקשות המקבילות שמופעלות waitForComplete() בקוד JavaScript חורג מהמגבלה שהוגדרה מראש.
  2. קשה לאבחן את הסיבה לבעיה כי ה-JavaScript נכשל עם השגיאה Timed out גם אם לא חלף הזמן המקסימלי שמוגדר במדיניות ה-JavaScript הספציפית.

שיטה מומלצת

מומלץ להשתמש בפונקציות קריאה חוזרת בלקוח ה-HTTP כדי לייעל את קוד הקריאה החוזרת ולשפר את הביצועים, ולהימנע משימוש ב-waitForComplete() בקוד JavaScript. השיטה הזו מבטיחה שהשרשור שמבצע JavaScript לא ייחסם עד להשלמת בקשת ה-HTTP.

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

קוד JavaScript לדוגמה שמשתמש בקריאות חוזרות ב-httpClient

function onComplete(response,error) {
 // Check if the HTTP request was successful
    if (response) {
      context.setVariable('example.status', response.status);
     } else {
      context.setVariable('example.error', 'Woops: ' + error);
     }
}
// Specify the callback Function as an argument
httpClient.get("http://example.com", onComplete);

קריאה נוספת