안티패턴: 자바스크립트 코드에서 waitForComplete() 사용

ApigeeApigee Hybrid 문서입니다.
Apigee Edge 문서 보기

자바스크립트 정책을 사용하면 API 프록시 흐름의 컨텍스트 내에서 실행되는 커스텀 코드를 추가할 수 있습니다. 예를 들어 자바스크립트 정책의 커스텀 코드는 다음과 같은 용도로 사용될 수 있습니다.

  • 흐름 변수 가져오기 및 설정
  • 커스텀 로직 실행 및 장애 처리 수행
  • 요청 또는 응답에서 데이터 추출
  • 백엔드 대상 URL을 동적으로 수정
  • 요청 또는 응답에서 동적으로 헤더 추가 또는 삭제
  • JSON 응답 파싱

HTTP 클라이언트

자바스크립트 정책의 강력한 기능은 HTTP 클라이언트입니다. HTTP 클라이언트(또는 httpClient 객체)를 사용하여 백엔드 또는 외부 서비스를 한 번 이상 호출할 수 있습니다. HTTP 클라이언트는 여러 외부 서비스를 호출하고 여러 응답을 단일 API에 결합해야 할 때 특히 유용합니다.

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 요청을 수행하기 위해 getsend 라는 2가지 메서드를 노출합니다(위의 샘플 코드에서는 send가 사용됨). 두 메서드는 모두 비동기식이며 실제 HTTP 요청이 완료되기 전에 exchange 객체를 반환합니다.

HTTP 요청은 몇 초에서 몇 분 정도 걸릴 수 있습니다. HTTP 요청이 수행된 후 요청의 응답이 처리될 수 있도록 완료 시점을 아는 것이 중요합니다. HTTP 요청이 완료되었는지 확인하는 가장 일반적인 방법 중 하나는 exchange 객체의 waitForComplete() 메서드를 호출하는 것입니다.

waitForComplete()

waitForComplete() 메서드는 HTTP 요청이 완료되고 응답(성공/실패)이 반환될 때까지 스레드를 일시중지합니다. 그러면 백엔드 또는 외부 서비스의 응답이 처리될 수 있습니다.

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

안티패턴

자바스크립트 코드에서 HTTP 요청을 전송한 후 waitForComplete()를 사용하면 성능에 영향이 있습니다.

HTTP 요청을 전송한 후에는 waitForComplete()를 호출하는 다음과 같은 자바스크립트 코드를 고려하세요.

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', response.status);
} else {
   error = exchangeObj.getError();
   context.setVariable('example.error', 'Woops: ' + error);
}

예를 들면 다음과 같습니다.

  1. 자바스크립트 코드가 백엔드 API에 HTTP 요청을 전송합니다.
  2. 그런 다음 waitForComplete()를 호출하여 요청이 완료될 때까지 실행을 일시중지합니다.

    waitForComplete() API는 백엔드가 요청 처리를 완료하고 다시 응답할 때까지 자바스크립트 코드를 실행하는 스레드가 차단되도록 합니다.

언제든지 메시지 프로세서에서 자바스크립트 코드를 동시에 실행할 수 있는 스레드 수는 상한(30%)이 정해져 있습니다. 이 제한에 도달하면 스레드가 자바스크립트 코드를 실행할 수 없습니다. 따라서 자바스크립트 코드에 waitForComplete() API를 실행하는 동시 요청이 너무 많으면 500 Internal Server ErrorTimed out 오류 메시지(자바스크립트 정책 제한 시간이 경과되지 않은 경우에도)와 함께 후속 요청이 실패합니다.

일반적으로 백엔드에서 요청을 처리하는 데 시간이 오래 걸리거나 트래픽이 많은 경우 이러한 상황이 발생할 수 있습니다.

영향

  1. 자바스크립트 코드에서 waitForComplete()를 실행하는 동시 요청 수가 사전 정의된 한도를 초과하면 500 Internal Server Error Timed out 오류 메시지가 표시되고 API 요청이 실패합니다.
  2. 특정 자바스크립트 정책의 시간 제한이 경과되지 않았어도 자바스크립트가 Timed out 오류와 함께 실패하므로 문제의 원인을 진단하기가 어려울 수 있습니다.

권장사항

HTTP 클라이언트의 콜백을 사용하면 콜아웃 코드를 간소화하고 성능을 개선하며 자바스크립트 코드에서 waitForComplete() 사용을 피할 수 있습니다. 이 방법을 사용하면 HTTP 요청이 완료될 때까지 자바스크립트를 실행하는 스레드가 차단되지 않습니다.

콜백을 사용하면 스레드가 자바스크립트 코드의 HTTP 요청을 전송하고 풀로 반환합니다. 스레드가 더 이상 차단되지 않으므로 다른 요청을 처리할 수 있습니다. HTTP 요청이 완료되고 콜백을 실행할 준비가 되면 태스크가 생성되어 태스크 큐에 추가됩니다. 풀의 스레드 중 하나가 태스크 우선순위에 따라 콜백을 실행합니다.

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

추가 자료