Azure Functions 오류 처리 및 다시 시도

Azure Functions의 오류를 처리하는 작업은 손실된 데이터, 누락된 이벤트를 방지하고 애플리케이션의 상태를 모니터링하는 데 중요합니다. 또한 이벤트 기반 트리거의 다시 시도 동작을 이해하는 것도 중요합니다.

이 문서에서는 오류 처리에 대한 일반적인 전략과 사용 가능한 다시 시도 전략에 대해 설명합니다.

Important

특정 트리거에 대한 미리 보기 재시도 정책 지원은 2022년 12월에 제거되었습니다. 지원되는 트리거에 대한 다시 시도 정책이 이제 GA(일반 공급)됩니다. 현재 다시 시도 정책을 지원하는 확장 목록은 다시 시도 섹션을 참조하세요.

오류 처리

Azure 함수에서 발생하는 오류는 다음에서 발생할 수 있습니다.

  • 기본 제공된 Functions 트리거 및 바인딩을 사용합니다.
  • 기본 Azure 서비스의 API에 대한 호출
  • REST 엔드포인트에 대한 호출
  • 클라이언트 라이브러리, 패키지 또는 타사 API에 대한 호출

데이터 손실이나 누락된 메시지를 방지하려면 좋은 오류 처리를 연습하는 것이 중요합니다. 이 표에서는 몇 가지 권장되는 오류 처리 방법을 설명하고 추가 정보에 대한 링크를 제공합니다.

추천 세부 정보
Application Insights 사용 Azure Functions는 Application Insights와 통합하여 오류 데이터, 성능 데이터 및 런타임 로그를 수집합니다. Application Insights를 사용하여 함수 실행에서 발생하는 오류를 검색하고 더 잘 이해해야 합니다. 자세히 알아보려면 Azure Functions 모니터링을 참조하세요.
구조적 오류 처리 사용 오류 캡처 및 로깅은 애플리케이션의 상태를 모니터링하는 데 매우 중요합니다. 함수 코드의 최상위 수준에는 Try/Catch 블록이 포함되어야 합니다. Catch 블록에서 오류를 캡처 및 기록할 수 있습니다. 바인딩으로 인해 발생할 수 있는 오류에 대한 자세한 내용은 바인딩 오류 코드를 참조하세요. 특정 다시 시도 전략에 따라 함수를 다시 실행하기 위해 새 예외가 발생할 수도 있습니다.
다시 시도 전략 계획 여러 Functions 바인딩 확장은 다시 시도에 대한 기본 지원을 제공하고 다른 확장에서는 Functions 런타임에서 구현되는 다시 시도 정책을 정의할 수 있습니다. 다시 시도 동작을 제공하지 않는 트리거의 경우 자체 다시 시도 체계를 구현하는 것을 고려해야 합니다. 자세한 내용은 다시 시도를 참조하세요.
멱등원을 위한 디자인 데이터를 처리할 때 오류가 발생하는 것은 특히 메시지를 처리할 때 함수에 대한 문제일 수 있습니다. 오류가 발생할 때 수행되는 작업과 중복 처리를 방지하는 방법을 고려해야 합니다. 자세한 내용은 동일한 입력에 대한 Azure Functions 디자인을 참조하세요.

재시도

함수에 사용할 수 있는 두 가지 유형의 다시 시도가 있습니다.

  • 개별 트리거 확장의 기본 제공 다시 시도 동작
  • 함수 런타임에서 제공하는 다시 시도 정책

다음 표에서는 다시 시도를 지원하는 트리거와 다시 시도 동작이 구성되는 위치를 나타냅니다. 또한 기본 서비스에서 발생하는 오류에 대한 자세한 정보로도 연결됩니다.

트리거/바인딩 다시 시도 원본 구성
Azure Cosmos DB 다시 시도 정책 함수 수준
Blob Storage 바인딩 확장 host.json
Event Grid 바인딩 확장 이벤트 구독
Event Hubs 다시 시도 정책 함수 수준
Kafka 다시 시도 정책 함수 수준
Queue Storage 바인딩 확장 host.json
RabbitMQ 바인딩 확장 배달 못한 편지 큐
Service Bus 바인딩 확장 host.json*
타이머 다시 시도 정책 함수 수준

*Azure Service Bus 확장 버전 5.x가 필요합니다. 이전 확장 버전에서는 다시 시도 동작이 Service Bus 데드레터 큐에 의해 구현됩니다.

재시도 정책

Azure Functions를 사용하면 런타임에 의해 적용되는 특정 트리거 형식에 대한 다시 시도 정책을 정의할 수 있습니다. 현재 다시 시도 정책을 지원하는 트리거 형식은 다음과 같습니다.

다시 시도 지원은 v1 및 v2 Python 프로그래밍 모델 모두에서 동일합니다.

Functions 런타임 버전 1.x에서는 다시 시도 정책이 지원되지 않습니다.

다시 시도 정책은 성공적인 완료가 발생하거나 최대 다시 시도 횟수에 도달할 때까지 실패한 실행을 다시 실행하도록 런타임에 지시합니다.

지원되는 트리거 형식에 의해 실행되는 함수가 catch되지 않은 예외를 발생시킬 때 재시도 정책이 평가됩니다. 코드에서 모든 예외를 catch하고 다시 시도하려는 오류에 대해 새 예외를 발생시키는 것이 가장 좋습니다.

Important

Event Hubs 검사점은 실행에 대한 재시도 정책이 완료될 때까지 기록되지 않습니다. 이 동작으로 인해 현재 일괄 처리가 완료될 때까지 특정 파티션의 진행이 일시 중지됩니다.

Event Hubs 확장 버전 5.x는 Functions 호스트와 Event Hubs 간의 상호 작용을 위한 추가 다시 시도 기능을 지원합니다. 자세한 내용은 Event Hubs host.json 참조clientRetryOptions를 참조하세요.

재시도 전략

정책에서 지원하는 두 가지 다시 시도 전략을 구성할 수 있습니다.

지정된 시간이 각 다시 시도 간에 경과할 수 있습니다.

사용량 계획을 실행하는 경우 함수 코드가 실행되는 시간에 대해서만 요금이 청구됩니다. 이러한 다시 시도 전략 중 하나에서 실행 간 대기 시간에 대해서는 요금이 청구되지 않습니다.

최대 다시 시도 횟수

최종 실패 전에 함수 실행이 다시 시도되는 최대 횟수를 구성할 수 있습니다. 현재 재시도 횟수는 인스턴스의 메모리에 저장됩니다.

인스턴스는 다시 시도 사이에 오류가 있을 수 있습니다. 재시도 정책 중에 인스턴스가 실패하면 재시도 횟수가 손실됩니다. 인스턴스 오류가 발생하면 Event Hubs 트리거에서 처리를 다시 시작하고 다시 시도 횟수를 0으로 다시 설정하여 새 인스턴스에서 일괄 처리를 다시 시도할 수 있습니다. 타이머 트리거는 새 인스턴스에서 다시 시작되지 않습니다.

이 동작은 최대 재시도 횟수가 최선의 노력임을 의미합니다. 경우에 따라 실행이 요청된 최대 횟수보다 더 많이 다시 시도될 수 있습니다. 타이머 트리거의 경우 다시 시도 횟수는 요청된 최대 횟수보다 작을 수 있습니다.

다시 시도 예제

고정 지연 및 지수 백오프 전략에 대한 예가 제공됩니다. 특정 전략의 예를 보려면 먼저 이전 탭에서 해당 전략을 선택해야 합니다.

함수 수준 재시도는 다음 NuGet 패키지에서 지원됩니다.

[Function(nameof(TimerFunction))]
[FixedDelayRetry(5, "00:00:10")]
public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo,
    FunctionContext context)
{
    var logger = context.GetLogger(nameof(TimerFunction));
    logger.LogInformation($"Function Ran. Next timer schedule = {timerInfo.ScheduleStatus.Next}");
}
속성 설명
MaxRetryCount 필수입니다. 함수 실행당 허용되는 최대 재시도 횟수입니다. -1은 무기한으로 재시도하는 것을 의미합니다.
DelayInterval 다시 시도 사이에 사용되는 지연입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.

다음은 function.json 파일에 정의된 재시도 정책의 예입니다.

{
    "disabled": false,
    "bindings": [
        {
            ....
        }
    ],
    "retry": {
        "strategy": "fixedDelay",
        "maxRetryCount": 4,
        "delayInterval": "00:00:10"
    }
}

재시도 정책 정의에 대해 다음 속성을 설정할 수 있습니다.

속성 설명
전략 필수입니다. 사용하는 재시도 전략입니다. 유효한 값은 fixedDelay 또는 exponentialBackoff입니다.
maxRetryCount 필수입니다. 함수 실행당 허용되는 최대 재시도 횟수입니다. -1은 무기한으로 재시도하는 것을 의미합니다.
delayInterval fixedDelay 전략을 사용할 때 다시 시도 사이에 사용되는 지연입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.
minimumInterval exponentialBackoff 전략을 사용하는 경우 최소한의 다시 시도 지연 시간입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.
maximumInterval exponentialBackoff 전략을 사용하는 경우 최대 재시도 지연 시간입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.

트리거에 대한 재시도 정책을 정의하는 방법은 Node.js 버전에 따라 다릅니다.

다음은 고정 지연 다시 시도 전략을 사용하는 타이머 트리거 함수의 예입니다.

const { app } = require('@azure/functions');

app.timer('timerTriggerWithRetry', {
    schedule: '0 */5 * * * *',
    retry: {
        strategy: 'fixedDelay',
        delayInterval: {
            seconds: 10,
        },
        maxRetryCount: 4,
    },
    handler: (myTimer, context) => {
        if (context.retryContext?.retryCount < 2) {
            throw new Error('Retry!');
        } else {
            context.log('Timer function processed request.');
        }
    },
});

트리거에 대한 재시도 정책을 정의하는 방법은 Node.js 버전에 따라 다릅니다.

다음은 고정 지연 다시 시도 전략을 사용하는 타이머 트리거 함수의 예입니다.

import { app, InvocationContext, Timer } from '@azure/functions';

export async function timerTriggerWithRetry(myTimer: Timer, context: InvocationContext): Promise<void> {
    if (context.retryContext?.retryCount < 2) {
        throw new Error('Retry!');
    } else {
        context.log('Timer function processed request.');
    }
}

app.timer('timerTriggerWithRetry', {
    schedule: '0 */5 * * * *',
    retry: {
        strategy: 'fixedDelay',
        delayInterval: {
            seconds: 10,
        },
        maxRetryCount: 4,
    },
    handler: timerTriggerWithRetry,
});

재시도 정책 정의에 대해 다음 속성을 설정할 수 있습니다.

속성 설명
전략 필수입니다. 사용하는 재시도 전략입니다. 유효한 값은 fixedDelay 또는 exponentialBackoff입니다.
maxRetryCount 필수입니다. 함수 실행당 허용되는 최대 재시도 횟수입니다. -1은 무기한으로 재시도하는 것을 의미합니다.
delayInterval fixedDelay 전략을 사용할 때 다시 시도 사이에 사용되는 지연입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.
minimumInterval exponentialBackoff 전략을 사용하는 경우 최소한의 다시 시도 지연 시간입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.
maximumInterval exponentialBackoff 전략을 사용하는 경우 최대 재시도 지연 시간입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.

다음은 고정 지연 다시 시도 전략을 사용하는 타이머 트리거 함수의 예입니다.

from azure.functions import FunctionApp, TimerRequest, Context, AuthLevel
import logging

app = FunctionApp(http_auth_level=AuthLevel.ANONYMOUS)


@app.timer_trigger(schedule="*/1 * * * * *", arg_name="mytimer",
                   run_on_startup=False,
                   use_monitor=False)
@app.retry(strategy="fixed_delay", max_retry_count="3",
           delay_interval="00:00:01")
def mytimer(mytimer: TimerRequest, context: Context) -> None:
    logging.info(f'Current retry count: {context.retry_context.retry_count}')

    if context.retry_context.retry_count == \
            context.retry_context.max_retry_count:
        logging.info(
            f"Max retries of {context.retry_context.max_retry_count} for "
            f"function {context.function_name} has been reached")
    else:
        raise Exception("This is a retryable exception")

재시도 정책 정의에 대해 다음 속성을 설정할 수 있습니다.

속성 설명
전략 필수입니다. 사용하는 재시도 전략입니다. 유효한 값은 fixed_delay 또는 exponential_backoff입니다.
max_retry_count 필수입니다. 함수 실행당 허용되는 최대 재시도 횟수입니다. -1은 무기한으로 재시도하는 것을 의미합니다.
delay_interval fixed_delay 전략을 사용할 때 다시 시도 사이에 사용되는 지연입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.
minimum_interval exponential_backoff 전략을 사용하는 경우 최소한의 다시 시도 지연 시간입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.
maximum_interval exponential_backoff 전략을 사용하는 경우 최대 재시도 지연 시간입니다. HH:mm:ss 형식을 사용하여 문자열로 지정합니다.
@FunctionName("TimerTriggerJava1")
@FixedDelayRetry(maxRetryCount = 4, delayInterval = "00:00:10")
public void run(
    @TimerTrigger(name = "timerInfo", schedule = "0 */5 * * * *") String timerInfo,
    final ExecutionContext context
) {
    context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
}

바인딩 오류 코드

Azure 서비스와 통합할 경우 기본 서비스의 API에서 오류가 발생할 수 있습니다. 바인딩 관련 오류에 대한 정보는 다음 문서의 “예외 및 반환 코드” 섹션에서 사용할 수 있습니다.

다음 단계