Антипаттерн: использование waitForComplete() в коде JavaScript

Вы просматриваете документацию по Apigee Edge.
Перейдите к документации по Apigee X.
Информация

Правило JavaScript в Apigee Edge позволяет добавлять собственный код, который выполняется в контексте потока прокси-сервера API. Например, с помощью пользовательского кода в правиле JavaScript можно:

  • Как получать и задавать переменные потока
  • Выполнение пользовательской логики и обработка ошибок
  • Как извлекать данные из запросов или ответов
  • Динамическое изменение целевого URL на стороне сервера
  • Как динамически добавлять или удалять заголовки в запросе или ответе
  • Как обработать ответ JSON

HTTP-клиент

Мощная функция правил JavaScript – клиент HTTP. Клиент HTTP (или объект httpClient) можно использовать для одного или нескольких вызовов внутренних или внешних сервисов. 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 предоставляет два метода для отправки HTTP-запросов: get и send (в приведенном выше образце кода используется send). Оба метода являются асинхронными и возвращают объект exchange до того, как будет выполнен HTTP-запрос.

HTTP-запросы могут выполняться от нескольких секунд до нескольких минут. После отправки 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 в Message Processor. После достижения этого лимита потоки для выполнения кода JavaScript будут недоступны. Поэтому, если в коде JavaScript выполняется слишком много одновременных запросов к API waitForComplete(), последующие запросы будут завершаться с ошибкой 500 Internal Server Error и сообщением "Время ожидания истекло" ещё до того, как истечет время ожидания правил JavaScript.

Как правило, это происходит, если обработка запросов на сервере занимает много времени или если трафик очень высокий.

Результат

  1. Если количество одновременно выполняемых запросов waitForComplete() в коде JavaScript превышает заданный лимит, запросы API будут завершаться ошибкой 500 Internal Server Error с сообщением "Время ожидания истекло".
  2. Определить причину проблемы может быть сложно, поскольку JavaScript завершается с ошибкой "Время ожидания истекло", даже если время, отведенное на выполнение скрипта, ещё не прошло.

Рекомендации

Используйте обратные вызовы в HTTP-клиенте, чтобы упростить код вызова и повысить производительность, а также избегайте использования waitForComplete() в коде JavaScript. Этот метод гарантирует, что поток, выполняющий код JavaScript, не будет заблокирован до завершения HTTP-запроса.

При использовании обратного вызова поток отправляет HTTP-запросы в коде JavaScript и возвращается в пул. Поскольку поток больше не заблокирован, он может обрабатывать другие запросы. После того как HTTP-запрос будет выполнен и обратный вызов будет готов к выполнению, задача будет создана и добавлена в очередь задач. Один из потоков из пула выполнит обратный вызов в зависимости от приоритета задачи.

Пример кода JavaScript с использованием обратных вызовов в 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);

Дополнительные материалы