Antipattern: ใช้ pendingForComplete() ในโค้ด JavaScript

คุณกำลังดูเอกสารประกอบของ Apigee Edge
ไปที่เอกสารประกอบของ Apigee X
ข้อมูล

นโยบาย JavaScript ใน Apigee Edge ช่วยให้คุณเพิ่มโค้ดที่กำหนดเองซึ่งจะทำงานภายในบริบทของโฟลว์พร็อกซี API ได้ เช่น โค้ดที่กำหนดเองในนโยบาย JavaScript สามารถใช้เพื่อวัตถุประสงค์ต่อไปนี้

  • รับและตั้งค่าตัวแปรโฟลว์
  • ดำเนินการตรรกะที่กำหนดเองและจัดการข้อผิดพลาด
  • ดึงข้อมูลจากคำขอหรือคำตอบ
  • แก้ไข URL เป้าหมายแบ็กเอนด์แบบไดนามิก
  • เพิ่มหรือนำส่วนหัวออกจากคำขอหรือการตอบกลับแบบไดนามิก
  • แยกวิเคราะห์การตอบกลับ JSON

ไคลเอ็นต์ HTTP

ฟีเจอร์ที่มีประสิทธิภาพของนโยบาย JavaScript คือไคลเอ็นต์ HTTP ไคลเอ็นต์ HTTP (หรือออบเจ็กต์ httpClient) จะใช้ในการเรียกแบ็กเอนด์หรือบริการภายนอก 1 ครั้งหรือหลายครั้งก็ได้ ไคลเอ็นต์ HTTP มีประโยชน์อย่างยิ่งเมื่อจำเป็นต้องเรียกไปยังบริการภายนอกหลายบริการ และรวมข้อมูลการตอบกลับไว้ใน API เดียว

ตัวอย่างโค้ด JavaScript ที่เรียกไปยังแบ็กเอนด์ด้วยออบเจ็กต์ httpClient

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

ออบเจ็กต์ httpClient แสดง 2 วิธี get และ send (send ในโค้ดตัวอย่างด้านบน) ในการสร้างคำขอ HTTP ทั้ง 2 วิธีไม่พร้อมกันและแสดงผลออบเจ็กต์ exchange ก่อนที่คำขอ HTTP จริงจะเสร็จสมบูรณ์

คำขอ HTTP อาจใช้เวลา 2-3 วินาทีไปจนถึง 2-3 นาที หลังจากที่สร้างคำขอ 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', response1.status);
} else {
   error = exchangeObj.getError();
   context.setVariable('example.error', 'Woops: ' + error);
}

ในตัวอย่างนี้

  1. โค้ด JavaScript จะส่งคำขอ HTTP ไปยัง API แบ็กเอนด์
  2. จากนั้นระบบจะเรียกใช้ waitForComplete() เพื่อหยุดการดำเนินการชั่วคราวจนกว่าคำขอจะเสร็จสมบูรณ์

    waitForComplete() API จะทำให้เทรดที่เรียกใช้โค้ด JavaScript ถูกบล็อกจนกว่าแบ็กเอนด์จะดำเนินการตามคำขอเสร็จสมบูรณ์และตอบกลับ

มีการจำกัดจำนวนชุดข้อความ (30%) ที่สามารถเรียกใช้โค้ด JavaScript พร้อมกันในเครื่องมือประมวลผลข้อความได้ทุกเมื่อ หลังจากถึงขีดจำกัดดังกล่าว จะไม่มีชุดข้อความให้เรียกใช้โค้ด JavaScript ดังนั้น หากมีคำขอที่ใช้งาน waitForComplete() API ในโค้ด JavaScript พร้อมกันมากเกินไป คำขอหลังจากนั้นจะไม่สำเร็จโดยมีข้อผิดพลาดภายในเซิร์ฟเวอร์ 500 และข้อความแสดงข้อผิดพลาด "หมดเวลา" ก่อนที่นโยบาย JavaScript จะหมดเวลา

โดยทั่วไป สถานการณ์นี้อาจเกิดขึ้นหากแบ็กเอนด์ใช้เวลานานในการดำเนินการตามคำขอหรือมีการเข้าชมสูง

มีอิทธิพล

  1. คำขอ API จะล้มเหลวโดยมีข้อผิดพลาดเซิร์ฟเวอร์ภายใน 500 และ มีข้อความแสดงข้อผิดพลาด "หมดเวลา" เมื่อจำนวนคำขอหลายรายการพร้อมกันที่ดำเนินการ waitForComplete() ในโค้ด JavaScript เกินขีดจำกัดที่กำหนดไว้ล่วงหน้า
  2. การวินิจฉัยสาเหตุของปัญหาอาจทำได้ยากเนื่องจาก JavaScript ล้มเหลวโดยมีข้อผิดพลาด "หมดเวลา" แม้ว่าเวลาที่กำหนดสำหรับนโยบาย JavaScript ที่เฉพาะเจาะจงจะยังไม่ผ่านไปก็ตาม

แนวทางปฏิบัติแนะนำ

ใช้โค้ดเรียกกลับในไคลเอ็นต์ HTTP เพื่อปรับปรุงโค้ดไฮไลต์และปรับปรุงประสิทธิภาพ รวมถึงหลีกเลี่ยงการใช้ waitForComplete() ในโค้ด JavaScript วิธีนี้ช่วยป้องกันไม่ให้เทรดที่เรียกใช้ JavaScript ถูกบล็อกจนกว่าคําขอ HTTP จะเสร็จสมบูรณ์

เมื่อมีการใช้โค้ดเรียกกลับ เทรดจะส่งคําขอ HTTP ในโค้ด JavaScript และกลับไปยังพูล ชุดข้อความไม่ได้ถูกบล็อกแล้ว คุณจึงจัดการคำขออื่นๆ ได้ หลังจากส่งคำขอ HTTP เสร็จสมบูรณ์และโค้ดเรียกกลับพร้อมที่จะดำเนินการแล้ว ระบบจะสร้างงานและเพิ่มไปยังคิวงาน เทรดรายการใดรายการหนึ่งจากพูลจะเรียกใช้โค้ดเรียกกลับตามลำดับความสำคัญของงาน

ตัวอย่างโค้ด JavaScript ที่ใช้ 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);

อ่านเพิ่มเติม