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 ที่มี payForComplete()

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

ลาย Antipattern

การใช้ 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 หนึ่งๆ ไปแล้ว

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

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

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

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

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