비동기 함수 재시도

이 문서에서는 실패 시 HTTPS가 아닌 비동기 백그라운드 함수를 요청하여 재시도하는 방법을 설명합니다.

재시도 의미 체계

Cloud Functions는 이벤트 소스에서 전송한 각 이벤트에 대해 백그라운드 함수를 최소한 1회 실행하도록 보장합니다. 하지만 기본적으로 함수 호출이 오류 발생으로 종료되면 해당 함수는 다시 호출되지 않으며 이벤트는 삭제됩니다. 백그라운드 함수에 재시도를 사용 설정하면 Cloud Functions는 실패한 함수 호출을 성공할 때까지 또는 재시도 기간이 만료할 때까지 다시 시도합니다.

백그라운드 함수를 완료하는 데 실패하는 이유

드문 경우지만 내부 오류로 인해 함수가 조기 종료될 수 있으며 기본값에 따라 함수가 자동으로 재시도되거나 재시도되지 않을 수 있습니다.

보통은 함수 코드 자체에 발생한 오류로 인해 백그라운드 함수를 완료하는 데 실패할 수 있습니다. 이러한 문제가 발생할 수 있는 이유는 다음과 같습니다.

  • 함수에 버그가 있으며 런타임에서 예외가 발생합니다.
  • 함수가 서비스 엔드포인트에 도달할 수 없거나 엔드포인트에 도달하려고 시도하는 중에 제한 시간이 초과하였습니다.
  • 예를 들어 매개변수가 유효성 검사에 실패하는 경우 등 함수에서 의도적인 예외가 발생합니다.
  • Node.js로 작성한 함수에서 거부된 프라미스를 반환하거나 null 외의 값을 콜백에 전달합니다.

위와 같은 경우 기본적으로 함수 실행이 중지되고 이벤트가 삭제됩니다. 오류 발생 시 함수를 재시도하려면 '실패 시 재시도' 속성을 설정하여 기본 재시도 정책을 변경하면 됩니다. 그러면 함수가 완료될 때까지 최대 며칠 동안 이벤트가 반복적으로 재시도됩니다.

재시도 사용 설정 및 중지

GCP Console 사용

다음과 같이 GCP 콘솔에서 재시도를 사용 설정하거나 중지할 수 있습니다.

  1. Cloud Platform 콘솔의 Cloud Functions 개요 페이지로 이동합니다.

  2. 함수 만들기를 클릭합니다. 또는 기존 함수를 클릭하여 세부정보 페이지로 이동하고 수정을 클릭합니다.

  3. 함수의 필수 필드를 작성합니다.

  4. 트리거 필드가 Cloud Pub/Sub 또는 Cloud Storage와 같은 백그라운드 함수 트리거 유형으로 설정되어 있는지 확인합니다.

  5. 더보기를 클릭하여 고급 설정을 펼칩니다.

  6. 실패 시 재시도라는 라벨이 지정된 체크박스를 선택하거나 선택 해제합니다.

권장사항

이 섹션에서는 재시도 사용의 권장사항을 설명합니다.

재시도를 사용하여 일시적인 오류 처리

함수는 성공적으로 실행될 때까지 지속적으로 재시도되므로 재시도를 사용 설정하기 전에 테스트를 통해 버그와 같은 영구적인 오류를 코드에서 제거해야 합니다. 재시도는 불안정한 서비스 엔드포인트 또는 시간 초과와 같이 재시도하면 해결될 가능성이 매우 높은 간헐적이거나 일시적인 실패를 처리하는 데 가장 적합합니다.

무한 재시도 루프를 방지하기 위해 종료 조건 설정

재시도를 사용할 때 함수가 지속적인 루프에 빠지지 않도록 조치를 취하는 것이 좋습니다. 함수 처리가 시작되기 전에 명확하게 정의된 종료 조건을 포함하면 됩니다. 간단하면서도 효과적인 방법은 특정 시간보다 오래된 타임스탬프가 있는 이벤트를 삭제하는 것입니다. 이렇게 하면 지속적으로 실패하거나 예상한 것보다 오래 실패하는 경우 지나치게 많이 실행되는 것을 막을 수 있습니다.

예를 들어 다음 코드 스니펫은 10초보다 오래된 모든 이벤트를 삭제합니다.

const eventAgeMs = Date.now() - Date.parse(event.timestamp);
const eventMaxAgeMs = 10000;
if (eventAgeMs > eventMaxAgeMs) {
  console.log(`Dropping event ${event} with age[ms]: ${eventAgeMs}`);
  callback();
  return;
}

프라미스와 함께 catch 사용

재시도를 사용 설정하는 경우 프라미스에 catch를 추가하는 것이 좋습니다. Cloud Functions는 재시도해서는 안 되는 치명적인 오류를 파악하지 못하므로 치명적인 오류를 지원한다면 적절히 코드를 수정해야 합니다.

수행할 작업의 예는 다음과 같습니다.

return doFooAsync().catch((err) => {
    if (isFatal(err)) {
        console.error(`Fatal error ${err}`);
    }
    return Promise.reject(err);
});

재시도 가능한 백그라운드 함수 멱등성 만들기

재시도할 수 있는 백그라운드 함수는 멱등성이 있어야 합니다. 백그라운드 함수 멱등성을 만들기 위한 일반적인 가이드는 다음과 같습니다.

  • Stripe와 같은 다양한 외부 API를 사용하면 매개변수로 멱등 키를 제공할 수 있습니다. 이러한 API를 사용한다면 이벤트 ID를 멱등 키로 사용해야 합니다.
  • 멱등성이 있으면 재시도해도 안전하므로 최소 1회 전송 시 잘 작동합니다. 따라서 안정적인 코드를 작성하기 위한 일반적인 권장사항은 재시도와 멱등성을 결합하는 것입니다.
  • 코드가 내부적으로 멱등성이 있어야 합니다. 예를 들면 다음과 같습니다.
    • 결과를 변경하지 않고 변형이 2번 이상 발생할 수 있는지 확인합니다.
    • 상태가 변형되기 전에 트랜잭션에서 데이터베이스 상태를 쿼리합니다.
    • 모든 부가적인 결과에 자체적으로 멱등성이 있는지 확인합니다.
  • 코드에 관계없이 함수 외부에서 트랜잭션 검사를 시행합니다. 예를 들어 특정 이벤트 ID가 이미 처리되었음을 어딘가에 기록하는 상태를 유지합니다.
  • 중복 함수 호출을 대역 외로 처리합니다. 예를 들어 중복 함수가 호출된 후 정리하는 별도의 정리 프로세스를 둡니다.

다음에 대한 의견 보내기...

도움이 필요하시나요? 지원 페이지를 방문하세요.