Antipattern: Sử dụng WaitForComplete() trong mã JavaScript

Bạn đang xem tài liệu về Apigee Edge.
Chuyển đến tài liệu về Apigee X.
thông tin

Chính sách về JavaScript trong Apigee cho phép bạn thêm mã tuỳ chỉnh có thể thực thi trong bối cảnh luồng proxy API. Ví dụ: mã tuỳ chỉnh trong chính sách JavaScript có thể được dùng để:

  • Lấy và đặt các biến luồng
  • Thực thi logic tuỳ chỉnh và xử lý lỗi
  • Trích xuất dữ liệu từ các yêu cầu hoặc phản hồi
  • Chỉnh sửa động URL đích phụ trợ
  • Tự động thêm hoặc xoá tiêu đề khỏi yêu cầu hoặc phản hồi
  • Phân tích cú pháp phản hồi JSON

Ứng dụng HTTP

Một tính năng mạnh mẽ của chính sách JavaScript là ứng dụng HTTP. Bạn có thể dùng ứng dụng HTTP (hoặc đối tượng httpClient) để thực hiện một hoặc nhiều lệnh gọi đến phần phụ trợ hoặc các dịch vụ bên ngoài. Ứng dụng HTTP đặc biệt hữu ích khi cần thực hiện lệnh gọi đến nhiều dịch vụ bên ngoài và kết hợp các phản hồi trong một API duy nhất.

Mã JavaScript mẫu thực hiện lệnh gọi đến phần phụ trợ bằng đối tượng httpClient

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

Đối tượng httpClient cho thấy hai phương thức getsend (send được dùng trong mã mẫu ở trên) để tạo yêu cầu HTTP. Cả hai phương thức đều không đồng bộ và trả về một đối tượng exchange trước khi yêu cầu HTTP thực sự hoàn tất.

Các yêu cầu HTTP có thể mất từ vài giây đến vài phút. Sau khi tạo yêu cầu HTTP, điều quan trọng là bạn phải biết thời điểm yêu cầu hoàn tất để có thể xử lý phản hồi từ yêu cầu đó. Một trong những cách phổ biến nhất để xác định thời điểm hoàn tất yêu cầu HTTP là gọi phương thức waitForComplete() của đối tượng exchange.

waitForComplete()

Phương thức waitForComplete() tạm dừng luồng cho đến khi yêu cầu HTTP hoàn tất và phản hồi (thành công/không thành công) được trả về. Sau đó, phản hồi từ một phần phụ trợ hoặc dịch vụ bên ngoài có thể được xử lý.

Mã JavaScript mẫu với 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());
}

Phản mẫu

Việc sử dụng waitForComplete() sau khi gửi yêu cầu HTTP trong mã JavaScript sẽ có ảnh hưởng đến hiệu suất.

Hãy xem xét mã JavaScript sau đây gọi waitForComplete() sau khi gửi yêu cầu HTTP.

Mã cho 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);
}

Trong ví dụ này:

  1. Mã JavaScript gửi yêu cầu HTTP đến một API phụ trợ.
  2. Sau đó, phương thức này sẽ gọi waitForComplete() để tạm dừng quá trình thực thi cho đến khi yêu cầu hoàn tất.

    API waitForComplete() khiến luồng đang thực thi mã JavaScript bị chặn cho đến khi phần phụ trợ hoàn tất việc xử lý yêu cầu và phản hồi lại.

Có giới hạn trên về số lượng luồng (30%) có thể thực thi đồng thời mã JavaScript trên Trình xử lý thư bất cứ lúc nào. Sau khi đạt đến giới hạn đó, sẽ không còn bất kỳ luồng nào để thực thi mã JavaScript. Vì vậy, nếu có quá nhiều yêu cầu đồng thời thực thi API waitForComplete() trong mã JavaScript, thì các yêu cầu tiếp theo sẽ không thực hiện được kèm theo thông báo lỗi 500 Internal Server Error (Lỗi máy chủ nội bộ 500) và thông báo lỗi "Timed out" (Đã hết giờ) ngay cả trước khi chính sách JavaScript hết thời gian chờ.

Nhìn chung, trường hợp này có thể xảy ra nếu phần phụ trợ mất nhiều thời gian để xử lý yêu cầu hoặc có lưu lượng truy cập cao.

Mức độ tác động

  1. Các yêu cầu API sẽ không thành công kèm theo Lỗi máy chủ nội bộ 500 kèm theo thông báo lỗi "Đã hết thời gian chờ" khi số lượng yêu cầu đồng thời thực thi waitForComplete() trong mã JavaScript vượt quá giới hạn định sẵn.
  2. Có thể bạn sẽ khó có thể chẩn đoán nguyên nhân của vấn đề này vì JavaScript gặp lỗi "Hết thời gian chờ" ngay cả khi giới hạn thời gian cho chính sách JavaScript cụ thể chưa hết.

Phương pháp hay nhất

Sử dụng các lệnh gọi lại trong ứng dụng HTTP để đơn giản hoá mã chú thích và cải thiện hiệu suất, đồng thời tránh sử dụng waitForComplete() trong mã JavaScript. Phương thức này đảm bảo rằng luồng thực thi JavaScript không bị chặn cho đến khi yêu cầu HTTP hoàn tất.

Khi lệnh gọi lại được sử dụng, luồng này sẽ gửi yêu cầu HTTP trong mã JavaScript và quay trở lại nhóm. Vì luồng không còn bị chặn nên có thể xử lý các yêu cầu khác. Sau khi yêu cầu HTTP hoàn tất và lệnh gọi lại đã sẵn sàng để thực thi, một tác vụ sẽ được tạo và thêm vào hàng đợi tác vụ. Một trong các luồng từ nhóm sẽ thực thi lệnh gọi lại dựa trên mức độ ưu tiên của tác vụ.

Mã JavaScript mẫu sử dụng các lệnh gọi lại trong 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);

Tài liệu đọc thêm