Antipattern: از waitForComplete() در کد جاوا اسکریپت استفاده کنید

شما در حال مشاهده مستندات Apigee Edge هستید.
به مستندات Apigee X مراجعه کنید .
اطلاعات

سیاست جاوا اسکریپت در Apigee Edge به شما امکان می‌دهد کد سفارشی اضافه کنید که در چارچوب یک جریان پروکسی API اجرا شود. به عنوان مثال، کد سفارشی در سیاست جاوا اسکریپت می‌تواند برای موارد زیر استفاده شود:

  • دریافت و تنظیم متغیرهای جریان
  • اجرای منطق سفارشی و مدیریت خطا
  • استخراج داده‌ها از درخواست‌ها یا پاسخ‌ها
  • ویرایش پویای URL هدف بک‌اند
  • به صورت پویا هدرها را از یک درخواست یا پاسخ اضافه یا حذف کنید
  • تجزیه یک پاسخ JSON

کلاینت HTTP

یکی از ویژگی‌های قدرتمند سیاست جاوا اسکریپت، کلاینت HTTP است. کلاینت HTTP (یا شیء httpClient ) می‌تواند برای برقراری یک یا چند فراخوانی به سرویس‌های backend یا خارجی استفاده شود. کلاینت HTTP به ویژه زمانی مفید است که نیاز به برقراری فراخوانی به چندین سرویس خارجی و ترکیب پاسخ‌ها در یک API واحد باشد.

نمونه کد جاوا اسکریپت برای فراخوانی 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 ارائه می‌دهد. هر دو متد ناهمزمان هستند و قبل از تکمیل درخواست HTTP واقعی، یک شیء exchange برمی‌گردانند.

درخواست‌های HTTP ممکن است از چند ثانیه تا چند دقیقه طول بکشند. پس از ارسال یک درخواست HTTP، مهم است که بدانید چه زمانی تکمیل شده است تا پاسخ درخواست بتواند پردازش شود. یکی از رایج‌ترین روش‌ها برای تعیین زمان تکمیل درخواست HTTP، فراخوانی متد waitForComplete() از شیء exchange است.

منتظر بمانید تا کامل شود()

متد waitForComplete() تا زمانی که درخواست HTTP کامل شود و پاسخی (موفق/ناموفق) برگردانده شود، thread را متوقف می‌کند. سپس، پاسخ از یک سرویس backend یا خارجی می‌تواند پردازش شود.

نمونه کد جاوا اسکریپت با تابع 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 در کد جاوا اسکریپت، پیامدهای عملکردی خواهد داشت.

کد جاوا اسکریپت زیر را در نظر بگیرید که پس از ارسال یک درخواست HTTP، تابع waitForComplete() را فراخوانی می‌کند.

کد مربوط به 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', response1.status);
} else {
   error = exchangeObj.getError();
   context.setVariable('example.error', 'Woops: ' + error);
}

در این مثال:

  1. کد جاوا اسکریپت یک درخواست HTTP به یک API بک‌اند ارسال می‌کند.
  2. سپس تابع waitForComplete() را فراخوانی می‌کند تا اجرا را تا زمان تکمیل درخواست متوقف کند.

    تابع waitForComplete() باعث می‌شود نخی که کد جاوااسکریپت را اجرا می‌کند، تا زمانی که بک‌اند پردازش درخواست را تکمیل کرده و پاسخ دهد، مسدود شود.

یک محدودیت بالایی (30%) برای تعداد رشته‌هایی (threads) وجود دارد که می‌توانند همزمان کد جاوا اسکریپت را در یک پردازشگر پیام (Message Processor) در هر زمان اجرا کنند. پس از رسیدن به این محدودیت، هیچ رشته‌ای برای اجرای کد جاوا اسکریپت در دسترس نخواهد بود. بنابراین، اگر درخواست‌های همزمان زیادی برای اجرای API waitForComplete() در کد جاوا اسکریپت وجود داشته باشد، درخواست‌های بعدی حتی قبل از اتمام مهلت سیاست جاوا اسکریپت، با خطای 500 Internal Server Error و پیام خطای 'Timed out' مواجه می‌شوند.

به طور کلی، این سناریو ممکن است زمانی رخ دهد که پردازش درخواست‌ها توسط backend زمان زیادی طول بکشد یا ترافیک زیادی وجود داشته باشد.

تأثیر

  1. درخواست‌های API با خطای ۵۰۰ Internal Server Error و مواجه می‌شوند. با پیام خطای 'Timed out' زمانی که تعداد درخواست‌های همزمان که waitForComplete() را در کد جاوا اسکریپت اجرا می‌کنند از حد از پیش تعریف شده فراتر می‌رود.
  2. تشخیص علت مشکل می‌تواند دشوار باشد زیرا جاوا اسکریپت با خطای «پایان زمان» از کار می‌افتد، حتی اگر محدودیت زمانی برای سیاست خاص جاوا اسکریپت به پایان نرسیده باشد.

بهترین روش

از callbackها در کلاینت HTTP برای ساده‌سازی کد callout و بهبود عملکرد استفاده کنید و از waitForComplete() در کد جاوا اسکریپت خودداری کنید. این روش تضمین می‌کند که نخ اجرای جاوا اسکریپت تا زمان تکمیل درخواست HTTP مسدود نشود.

وقتی از یک فراخوانی برگشتی استفاده می‌شود، نخ درخواست‌های HTTP را در کد جاوا اسکریپت ارسال می‌کند و به مخزن برمی‌گرداند. از آنجایی که نخ دیگر مسدود نشده است، برای مدیریت سایر درخواست‌ها در دسترس است. پس از تکمیل درخواست HTTP و آماده شدن فراخوانی برگشتی برای اجرا، یک وظیفه ایجاد و به صف وظایف اضافه می‌شود. یکی از نخ‌های مخزن، فراخوانی برگشتی را بر اساس اولویت وظیفه اجرا خواهد کرد.

نمونه کد جاوا اسکریپت با استفاده از Callbackها در 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);

مطالعه بیشتر