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

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

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

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

سرویس گیرنده HTTP

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

نمونه کد جاوا اسکریپت که با شی httpClient یک تماس با backend برقرار می کند

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()

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

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

کد جاوا اسکریپت زیر را در نظر بگیرید که 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', response1.status);
} else {
   error = exchangeObj.getError();
   context.setVariable('example.error', 'Woops: ' + error);
}

در این مثال:

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

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

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

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

تاثیر

  1. درخواست های API با 500 خطای سرور داخلی و با پیغام خطا "Timed out" زمانی که تعداد درخواست‌های همزمان اجراکننده waitForComplete() در کد جاوا اسکریپت از حد از پیش تعریف شده فراتر رود.
  2. تشخیص علت مشکل می‌تواند مشکل باشد، زیرا جاوا اسکریپت با خطای "Timed out" شکست می‌خورد، حتی اگر محدودیت زمانی برای خط‌مشی خاص جاوا اسکریپت سپری نشده باشد.

بهترین تمرین

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

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

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

در ادامه مطلب