Azure Event Hubs 트리거와 함께 Azure Functions를 사용하여 강력하고 신뢰할 수 있는 서버리스 솔루션을 빌드하는 방법을 알아봅니다. 이 문서에서는 이벤트가 손실되지 않고 이벤트 기반 애플리케이션이 안정적이고 복원력 있게 유지되도록 검사점, 오류 처리 및 회로 차단기 패턴 구현에 대한 모범 사례를 설명합니다.
분산 시스템의 이벤트 스트림 문제
초당 100개 이벤트의 일정한 속도로 이벤트를 보내는 시스템을 고려합니다. 이 속도로 몇 분 내에 여러 병렬 인스턴스가 들어오는 100개의 이벤트를 초당 사용할 수 있습니다.
그러나 이벤트 스트림을 사용하는 데는 다음과 같은 문제를 고려해야 합니다.
- 이벤트 게시자가 손상된 이벤트를 보냅니다.
- 함수 코드에 처리되지 않은 예외가 발생합니다.
- 다운스트림 시스템은 오프라인 상태가 되며 이벤트 처리를 차단합니다.
처리 중에 메시지를 잠그는 Azure Queue Storage 트리거와 달리 Azure Event Hubs는 스트림의 단일 지점에서 파티션당 읽습니다. 비디오 플레이어와 더 유사한 이 읽기 동작은 높은 처리량, 여러 소비자 그룹 및 재생 기능의 원하는 이점을 제공합니다. 이벤트는 검사점에서 앞으로 또는 뒤로 읽혀지지만 포인터를 이동하여 새 이벤트를 처리해야 합니다. 자세한 내용은 Event Hubs 설명서의 검사점을 참조하세요.
스트림에서 오류가 발생하고 포인터를 진행하지 않도록 선택하면 추가 이벤트 처리가 차단됩니다. 즉, 단일 이벤트를 처리하는 문제를 처리하기 위해 포인터를 중지하면 처리되지 않은 이벤트가 쌓이기 시작합니다.
함수는 성공 또는 실패에 관계없이 항상 스트림의 포인터를 진행하여 교착 상태를 방지합니다. 포인터가 계속 진행되므로 함수는 오류를 적절하게 처리해야 합니다.
Event Hubs 트리거에서 이벤트를 소비하는 방법
Azure Functions는 다음 단계를 순환하여 이벤트 허브의 이벤트를 사용합니다.
- 이벤트 허브의 각 파티션에 대한 포인터가 만들어지고 Azure Storage에 유지됩니다.
- 새 이벤트는 기본적으로 일괄 처리로 수신되고 호스트는 처리를 위해 이벤트 일괄 처리를 제공하는 함수를 트리거하려고 합니다.
- 예외를 제외하고 함수가 실행을 완료하면 포인터가 고급이며 검사점이 기본 호스트 스토리지 계정에 저장됩니다.
- 조건에서 함수 실행이 완료되지 않는 경우 호스트는 포인터를 진행할 수 없습니다. 포인터가 앞으로 나아갈 수 없는 경우 후속 실행은 동일한 이벤트를 다시 처리합니다.
이 동작은 다음과 같은 몇 가지 중요한 사항을 표시합니다.
처리되지 않은 예외로 인해 이벤트가 손실될 수 있습니다.
예외를 발생시키는 함수 실행은 포인터를 계속 진행합니다. 재시도 정책 또는 기타 재시도 논리를 설정하면 전체 재시도가 완료될 때까지 포인터의 진행이 지연됩니다.
함수는 한 번 이상 배달을 보장합니다.
코드 및 종속 시스템은 동일한 이벤트를 두 번 처리할 수 있다는 사실을 고려해야 할 수 있습니다. 자세한 내용은 동일한 입력에 대한 Azure Functions 디자인을 참조하세요.
예외 처리
모든 함수 코드는 최고 수준의 코드에 try/catch 블록을 포함해야 하지만 Event catch
Hubs 이벤트를 사용하는 함수에는 블록이 더 중요합니다. 이렇게 하면 예외가 발생하면 catch 블록은 포인터가 진행되기 전에 오류를 처리합니다.
재시도 메커니즘 및 정책
클라우드의 많은 예외가 일시적이므로 오류 처리의 첫 번째 단계는 항상 작업을 다시 시도하는 것입니다. 기본 제공 재시도 정책을 적용하거나 고유한 재시도 논리를 정의할 수 있습니다.
재시도 정책
Functions는 기본적으로 Event Hubs에 대한 재시도 정책을 제공합니다. 재시도 정책을 사용하는 경우 새 예외를 발생시키고 호스트는 정의된 정책에 따라 이벤트를 다시 처리하려고 합니다. 이 재시도 동작에는 Event Hubs 확장 버전 5.x 이상이 필요합니다. 자세한 내용은 다시 시도 정책을 참조하세요.
사용자 지정 재시도 논리
함수 자체에서 사용자 고유의 재시도 논리를 정의할 수도 있습니다. 예를 들어 다음 규칙에 설명된 워크플로를 따르는 정책을 구현할 수 있습니다.
- 이벤트를 세 번 처리합니다(재시도 사이에 지연이 있을 수 있습니다).
- 모든 재시도의 최종 결과가 실패인 경우 스트림에서 처리를 계속할 수 있도록 큐에 이벤트를 추가합니다.
- 손상되거나 처리되지 않은 이벤트는 나중에 처리됩니다.
비고
Polly 는 C# 애플리케이션에 대한 복원력 및 일시적인 오류 처리 라이브러리의 예입니다.
비예외 오류
예외가 발생하지 않고 일부 문제가 발생할 수 있습니다. 예를 들어 요청 시간이 초과되거나 함수를 실행하는 인스턴스가 충돌하는 경우를 고려합니다. 예외 없이 함수를 완료하지 못하면 오프셋 포인터는 고급 상태가 되지 않습니다. 포인터가 진행되지 않으면 실패한 실행 후에 실행되는 모든 인스턴스가 동일한 이벤트를 계속 읽습니다. 이 상황은 최소 한 번 보장을 제공합니다.
모든 이벤트가 한 번 이상 처리된다는 보장은 일부 이벤트를 두 번 이상 처리할 수 있음을 의미합니다. 함수 앱은 이러한 가능성을 알고 있어야 하며 멱등성 원칙을 기반으로 구축되어야 합니다.
오류 상태 처리
앱은 이벤트 처리 중 몇 가지 오류를 적절하게 처리할 수 있습니다. 그러나 다운스트림 처리의 오류로 인해 발생할 수 있는 영구적 오류 상태를 처리할 준비가 되어 있어야 합니다. 다운스트림 데이터 저장소가 오프라인 상태인 등의 오류 상태에서는 시스템이 정상 상태에 도달할 때까지 함수가 이벤트에 대한 트리거를 중지해야 합니다.
회로 차단기 패턴
회로 차단기 패턴을 구현할 때 앱은 이벤트 처리를 효과적으로 일시 중지한 다음 문제가 해결된 후 나중에 다시 시작할 수 있습니다.
이벤트 스트림 프로세스에서 회로 차단기를 구현하는 데 필요한 두 가지 구성 요소가 있습니다.
- 회로의 상태를 추적하고 모니터링하기 위한 모든 인스턴스의 공유 상태입니다.
- 회로 상태를 관리할 수 있는 기본 프로세스입니다
open
closed
.
구현 세부 정보는 다를 수 있지만 인스턴스 간에 상태를 공유하려면 스토리지 메커니즘이 필요합니다. Azure Storage, Redis 캐시 또는 함수 앱 인스턴스에서 액세스할 수 있는 다른 영구 서비스에 상태를 저장할 수 있습니다.
Durable Functions와 Azure Logic Apps는 워크플로 및 회로 상태를 관리하는 인프라를 제공합니다. 이 문서에서는 Logic Apps를 사용하여 함수 실행을 일시 중지하고 다시 시작하여 회로 차단기 패턴을 구현하는 데 필요한 컨트롤을 제공하는 방법을 설명합니다.
인스턴스 간 오류 임계값 정의
여러 인스턴스가 동시에 이벤트를 처리하는 경우 회로의 상태를 모니터링하려면 지속형 공유 외부 상태가 필요합니다. 그런 다음 다음과 같이 오류 상태를 나타내는 규칙에 따라 이 지속형 상태를 모니터링할 수 있습니다.
모든 인스턴스에서 30초 동안 100개 이상의 이벤트 오류가 발생하면 회로를 중단하여 새 이벤트에 대한 트리거를 중지합니다.
이 모니터링 논리에 대한 구현 세부 정보는 특정 앱 요구 사항에 따라 다르지만 일반적으로 다음 시스템을 만들어야 합니다.
- 지속형 스토리지에 대한 오류를 기록합니다.
- 새 오류가 기록될 때 롤링 횟수를 검사하여 이벤트 실패 임계값이 충족되는지 확인합니다.
- 이 임계값에 도달하면 회로를 중단하도록 시스템에 알리는 이벤트를 내보냅니다.
Azure Logic Apps를 사용하여 회로 상태 관리
Azure Logic Apps는 다양한 서비스, 기능 및 상태 저장 오케스트레이션에 대한 기본 제공 커넥터와 함께 제공되며 회로 상태를 관리하는 것은 자연스러운 선택입니다. 회로가 중단되어야 하는 시기를 감지한 후 논리 앱을 빌드하여 이 워크플로를 구현할 수 있습니다.
- 함수 처리를 중지하는 Event Grid 워크플로를 트리거합니다.
- 워크플로를 다시 시작하는 옵션이 포함된 알림 이메일을 보냅니다.
앱 설정을 사용하여 특정 함수를 사용하지 않도록 설정하고 다시 설정하는 방법을 알아보려면 Azure Functions에서 함수를 사용하지 않도록 설정하는 방법을 참조하세요.
전자 메일 수신자는 회로의 상태를 조사하고 적절한 경우 알림 전자 메일의 링크를 통해 회로를 다시 시작할 수 있습니다. 워크플로가 함수를 다시 시작하면 마지막 이벤트 허브 검사점에서 이벤트가 처리됩니다.
이 방식을 사용하면 이벤트가 손실되지 않고, 이벤트가 순서대로 처리되며, 필요한 만큼 회로를 차단할 수 있습니다.
Event Grid 트리거에 대한 마이그레이션 전략
지역 간 또는 일부 계획 간에 기존 함수 앱을 마이그레이션하는 경우 마이그레이션 프로세스 중에 앱을 다시 만들어야 합니다. 이 경우 마이그레이션 프로세스 중에 동일한 이벤트 스트림에서 사용하고 동일한 출력 대상에 쓸 수 있는 두 개의 앱이 있을 수 있습니다.
마이그레이션 프로세스 중에 이벤트 데이터 손실 또는 중복을 방지하기 위해 소비자 그룹을 사용하는 것이 좋습니다.
새 대상 앱에 대한 새 소비자 그룹을 만듭니다.
이 새 소비자 그룹을 사용하도록 새 앱에서 트리거를 구성합니다.
이렇게 하면 두 앱이 유효성 검사 중에 독립적으로 이벤트를 처리할 수 있습니다.
새 앱이 이벤트를 올바르게 처리하고 있는지 확인합니다.
원래 앱을 중지하거나 구독/소비자 그룹을 제거합니다.