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

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

นโยบาย 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 Internal Server Error และพร้อมข้อความแสดงข้อผิดพลาด "หมดเวลา" เมื่อจํานวนคําขอที่ดําเนินการ 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);

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