복원력 있는 Event Hubs 및 Functions 디자인

오류 처리, 멱등성(idempotency) 설계 및 다시 시도 동작 관리는 Event Hubs 트리거 기능이 복원력 있고 대량의 데이터를 처리할 수 있도록 하기 위해 수행할 수 있는 몇 가지 중요한 조치입니다. 이 문서에서는 이러한 중요한 개념을 설명하고 서버리스 이벤트 스트리밍 솔루션에 대한 권장 사항을 제공합니다.

Azure는 다양한 고유한 이벤트 기반 시나리오를 지원하기 위해 Azure Functions에서 사용할 수 있는 세 가지 주요 메시징 서비스를 제공합니다. 분할된 소비자 모델과 빠른 속도로 데이터를 수집하는 기능으로 인해 Azure Event Hubs는 일반적으로 이벤트 스트리밍 및 빅 데이터 시나리오에 사용됩니다. Azure 메시징 서비스에 대한 자세한 비교는 Azure 메시징 서비스 - Event Grid, Event Hubs 및 Service Bus 중에서 선택을 참조하세요.

스트리밍의 이점 및 과제

스트림의 이점과 단점을 이해하면 Event Hubs와 같은 서비스가 작동하는 방식을 이해하는 데 도움이 됩니다. 또한 영향력 있는 아키텍처를 결정하고 문제를 해결하고 성능을 최적화하는 경우 이 컨텍스트가 필요합니다. Event Hubs 및 Functions를 모두 갖춘 솔루션에 대해 고려해야 할 주요 개념은 다음과 같습니다.

  • 스트림은 큐가 아님: Event Hubs, Kafka 및 분할된 소비자 모델을 기반으로 하는 기타 비슷한 제품은 기본적으로 Service Bus와 같은 메시지 broker의 일부 주요 기능을 지원하지 않습니다. 아마도 이에 대한 가장 큰 지표는 읽기가 비파괴적이라는 사실입니다. 즉, Functions 호스트에서 읽은 데이터는 나중에 삭제되지 않습니다. 대신 메시지는 변경할 수 없으며 잠재적으로 동일한 고객이 메시지를 다시 읽는 것을 포함하여 다른 소비자가 읽을 수 있도록 유지됩니다. 이러한 이유로 경쟁 소비자와 같은 패턴을 구현하는 솔루션이 기존 메시지 broker에 더 적합합니다.

  • 내재된 배달 못한 편지 지원 누락: 배달 못한 편지 채널은 Event Hubs 또는 Kafka의 기본 기능이 아닙니다. 배달 못한 편지의 개념은 처리할 수 없는 데이터를 처리하기 위해 스트리밍 솔루션에 통합되는 경우가 많습니다. 이 기능은 의도적으로 Event Hubs의 기본 요소가 아니며, 비슷한 동작 또는 효과를 만들기 위해 소비자 쪽에만 추가됩니다. 배달 못한 편지 지원이 필요한 경우 잠재적으로 스트리밍 메시지 서비스 선택을 검토해야 합니다.

  • 작업 단위는 파티션임: 기존 메시지 broker에서 작업 단위는 단일 메시지입니다. 스트리밍 솔루션에서 파티션은 작업 단위로 간주되는 경우가 많습니다. 이벤트 허브의 각 이벤트가 주문 처리 작업 또는 금융 거래처럼 처리되어야 하는 불연속 메시지로 간주되는 경우 잘못된 메시징 서비스가 사용되고 있음을 나타낼 가능성이 큽니다.

  • 서버 쪽 필터링 없음: Event Hubs에서 엄청난 규모와 처리량을 지원할 수 있는 이유 중 하나는 서비스 자체의 오버헤드가 낮기 때문입니다. 서버 쪽 필터링, 인덱스 및 broker 간 조정과 같은 기능은 Event Hubs 아키텍처의 일부가 아닙니다. Functions가 본문 또는 헤더의 콘텐츠에 따라 이벤트를 다른 Event Hubs로 라우팅하여 이벤트를 필터링하는 데 사용되는 경우가 있습니다. 이 방법은 이벤트 스트리밍에서 일반적이지만 초기 함수에서 각 이벤트를 읽고 평가한다는 주의 사항과 함께 제공됩니다.

  • 모든 판독기에서 모든 데이터를 읽어야 함: 서버 쪽 필터링을 사용할 수 없으므로 소비자는 파티션의 모든 데이터를 순차적으로 읽습니다. 여기에는 관련이 없거나 형식이 잘못되었을 수 있는 데이터가 포함됩니다. 이 섹션의 뒷부분에서 설명하는 이러한 과제를 보완하는 데 사용할 수 있는 몇 가지 옵션과 전략도 있습니다.

이러한 중요한 디자인 결정을 통해 Event Hubs는 가장 잘 수행할 수 있는 작업을 수행할 수 있습니다. 즉, 상당한 양의 이벤트 유입을 지원하고 소비자가 읽을 수 있는 강력하고 복원력 있는 서비스를 제공합니다. 각 소비자 애플리케이션은 이러한 이벤트에 대한 고유한 클라이언트 쪽 오프셋 또는 커서를 유지 관리해야 합니다. 낮은 오버헤드에 따라 Event Hubs는 이벤트 스트리밍을 위한 저렴하고 강력한 옵션이 됩니다.

멱등원

Azure Event Hubs의 핵심 원칙 중 하나는 한 번 이상 전달이라는 개념입니다. 이 방법을 사용하면 이벤트가 항상 전달됩니다. 또한 함수와 같은 소비자가 이벤트를 두 번 이상, 심지어 반복적으로 받을 수 있음을 의미합니다. 이러한 이유로 이벤트 허브 트리거 함수에서 멱등(idempotent) 소비자 패턴을 지원해야 합니다.

특히 이벤트 기반 아키텍처의 컨텍스트 내에서 한 번 이상 전달한다는 가정하에 작업하는 것은 이벤트를 안정적으로 처리하는 책임 있는 방법입니다. 함수는 동일한 이벤트를 여러 번 처리한 결과가 한 번 처리한 것과 동일하도록 멱등적(idempotent)이어야 합니다.

중복된 이벤트

중복 이벤트가 함수에 전달될 수 있는 몇 가지 다른 시나리오가 있습니다.

  • 검사점 설정: Azure Functions 호스트의 작동이 중단되거나 일괄 처리 검사점 빈도에 대해 설정된 임계값이 충족되지 않으면 검사점이 만들어지지 않습니다. 결과적으로 소비자에 대한 오프셋이 진행되지 않고 다음 번에 함수가 호출될 때 마지막 검사점에서 다시 시작됩니다. 검사점 설정은 각 소비자의 파티션 수준에서 발생합니다.

  • 게시된 중복 이벤트: 동일한 이벤트가 스트림에 게시될 가능성을 완화할 수 있는 많은 기술이 있지만, 중복을 멱등적으로 처리하는 것은 여전히 소비자가 수행해야 합니다.

  • 누락된 승인: 경우에 따라 서비스로 나가는 요청이 성공할 수 있지만 서비스로부터 승인(ACK)을 받지 못합니다. 이로 인해 나가는 호출이 실패했다고 인식할 수 있으며 일련의 작업, 다시 시도 또는 함수의 다른 결과를 시작할 수도 있습니다. 결국 중복 이벤트가 게시되거나 검사점이 만들어지지 않을 수 있습니다.

중복 제거 기술

동일한 입력을 위한 함수 설계는 Event Hub 트리거 바인딩과 함께 사용할 때 기본 방법이어야 합니다. 다음 기술을 고려해야 합니다.

  • 중복 찾기: 처리하기 전에 필요한 단계를 수행하여 이벤트를 처리해야 하는지 확인합니다. 경우에 따라 여전히 유효한지 확인하기 위해 조사가 필요합니다. 데이터 새로 고침 또는 이벤트 무효화 논리로 인해 이벤트 처리가 더 이상 필요하지 않을 수도 있습니다.

  • 멱등성을 위한 이벤트 디자인: 이벤트 페이로드 내에서 추가 정보를 제공하면 이벤트를 여러 번 처리해도 부정적인 영향을 미치지 않도록 할 수 있습니다. 예를 들어 은행 계좌에서 인출할 금액이 포함된 이벤트가 있습니다. 책임감 있게 처리하지 않으면 계정 잔액이 여러 번 감소할 수 있습니다. 그러나 계정에 대한 업데이트된 잔액이 동일한 이벤트에 포함되는 경우 은행 계정 잔액에 대한 upsert 작업을 수행하는 데 사용될 수 있습니다. 이 이벤트 수행 상태 전송 방법은 때때로 생산자와 소비자 간의 조정이 필요하며 참여 서비스에 적합할 때 사용해야 합니다.

오류 처리 및 재시도

오류 처리 및 다시 시도는 분산된 이벤트 기반 애플리케이션의 가장 중요한 특성 중 일부이며 Functions도 마찬가지입니다. 이벤트 스트리밍 솔루션의 경우 수천 개의 이벤트가 올바르게 처리되지 않으면 동일한 수의 오류로 빠르게 전환될 수 있으므로 적절한 오류 처리 지원이 필요합니다.

오류 처리 지침

오류 처리가 없으면 다시 시도를 구현하고, 런타임 예외를 검색하고, 문제를 조사하는 것이 까다로울 수 있습니다. 모든 함수에는 최소한 어느 정도의 수준 또는 오류 처리가 있어야 합니다. 몇 가지 권장 지침은 다음과 같습니다.

  • Application Insights 사용: Application Insights를 사용하도록 설정하고 이를 사용하여 오류를 로그하고 함수의 상태를 모니터링합니다. 많은 양의 이벤트를 처리하는 시나리오에 대해 구성 가능한 샘플링 옵션에 주의합니다.

  • 구조적 오류 처리 추가: 각 프로그래밍 언어에 적절한 오류 처리 구문을 적용하여 함수 코드에서 예상되는 예외 및 처리되지 않은 예외를 catch, 로그 및 검색합니다. 예를 들어 C#, Java 및 JavaScript에서 try/catch 블록을 사용하고 Python에서 try 및 except 블록을 활용하여 예외를 처리합니다.

  • 로깅: 실행 중에 예외를 catch하면 문제를 안정적으로 검색, 재현 및 수정하는 데 사용할 수 있는 중요한 정보를 로그할 수 있습니다. 예외, 즉 메시지뿐만 아니라 본문, 내부 예외 및 나중에 도움이 될 기타 유용한 아티팩트도 로그합니다.

  • 예외를 catch하고 무시하지 않음: 수행할 수 있는 최악의 작업 중 하나는 예외를 catch하고 아무 작업도 수행하지 않는 것입니다. 제네릭 예외가 catch되는 경우 어딘가에 로그합니다. 오류가 로그되지 않으면 버그 및 보고된 문제를 조사하기가 어렵습니다.

다시 시도

이벤트 스트리밍 아키텍처에서 다시 시도 논리를 구현하는 것은 복잡할 수 있습니다. 취소 토큰, 다시 시도 횟수 및 지수 백오프 전략을 지원하는 것은 이를 어렵게 하는 몇 가지 고려 사항일 뿐입니다. 다행히 Functions는 일반적으로 직접 코딩하는 이러한 많은 작업을 보충할 수 있는 다시 시도 정책을 제공합니다.

Event Hub 바인딩과 함께 다시 시도 정책을 사용하는 경우 고려해야 하는 몇 가지 중요한 요소는 다음과 같습니다.

  • 무한 다시 시도 방지:최대 다시 시도 횟수 설정이 -1 값으로 설정되면 함수에서 무한히 다시 시도합니다. 일반적으로 무한 다시 시도는 Functions에서 드물게 사용해야 하며 Event Hub 트리거 바인딩에서는 거의 사용하지 않아야 합니다.

  • 적절한 다시 시도 전략 선택:고정 지연 전략은 다른 Azure 서비스로부터 역 압력을 받는 시나리오에 가장 적합할 수 있습니다. 이러한 경우 지연은 해당 서비스에서 발생하는 제한 및 기타 제한 사항을 방지하는 데 도움이 될 수 있습니다. 지수 백오프 전략은 다시 시도 지연 간격에 더 많은 유연성을 제공하며 일반적으로 타사 서비스, REST 엔드포인트 및 기타 Azure 서비스와 통합할 때 사용됩니다.

  • 낮은 간격 및 다시 시도 횟수 유지: 가능하면 다시 시도 간격을 1분 미만으로 유지합니다. 또한 최대 다시 시도 횟수를 합리적으로 낮은 횟수로 유지합니다. 이러한 설정은 Functions 사용량 계획에서 실행할 때 특히 적합합니다.

  • 회로 차단기 패턴: 때때로 일시적인 오류가 예상되고 다시 시도에 대한 자연스러운 사용 사례가 있습니다. 그러나 함수를 처리하는 동안 상당한 수의 오류 또는 문제가 발생하는 경우 함수를 중지하고, 문제를 해결한 다음, 나중에 다시 시작하는 것이 좋습니다.

Functions의 다시 시도 정책에 대한 중요한 사항은 이벤트를 다시 처리하기 위한 최선의 작업 기능이라는 것입니다. 이는 복원력을 코드에 제공하는 오류 처리, 로깅 및 기타 중요한 패턴에 대한 필요성을 대체하지 않습니다.

오류 및 손상된 데이터에 대한 전략

이벤트 스트림의 오류 또는 잘못된 데이터로 인해 발생하는 문제를 보상하는 데 사용할 수 있는 몇 가지 주목할만한 방법이 있습니다. 몇 가지 기본 전략은 다음과 같습니다.

  • 보내기 및 읽기 중지: 이벤트 읽기 및 쓰기를 일시 중지하여 기본 문제를 해결합니다. 이 방법의 이점은 데이터가 손실되지 않고, 수정이 롤아웃된 후 작업을 다시 시작할 수 있다는 것입니다. 이 방법에는 아키텍처의 회로 차단기 구성 요소와 일시 중지를 수행하기 위해 영향을 받는 서비스에 대한 알림이 필요할 수 있습니다. 경우에 따라 문제가 해결될 때까지 함수를 중지해야 할 수도 있습니다.

  • 메시지 삭제: 메시지가 중요하지 않거나 중요하지 않은 것으로 간주되는 경우 계속 진행하여 처리하지 않는 것이 좋습니다. 이는 체스 경기 또는 금융 기반 거래에서 이동을 기록하는 것과 같이 강력한 일관성이 필요한 시나리오에서는 작동하지 않습니다. 처리할 수 없는 메시지를 catch하고 삭제하려면 함수 내부에서 오류를 처리하는 것이 좋습니다.

  • 다시 시도: 이벤트를 다시 처리하도록 보증할 수 있는 많은 경우가 있습니다. 가장 일반적인 시나리오는 다른 서비스 또는 종속성을 호출할 때 발생하는 일시적인 오류입니다. 네트워크 오류, 서비스 제한 및 가용성, 강력한 일관성은 아마도 다시 처리 시도를 정당화하는 가장 빈번한 사용 사례일 수 있습니다.

  • 배달 못한 편지: 여기서는 기존 흐름이 중단되지 않도록 이벤트를 다른 이벤트 허브에 게시하는 것이 좋습니다. 이 경우 핫 경로에서 벗어났으며 나중에 또는 다른 프로세스에서 처리될 수 있다고 인식합니다. 이 솔루션은 잘못된 메시지 또는 이벤트를 처리하는 데 자주 사용됩니다. 다른 소비자 그룹으로 구성된 각 함수는 여전히 스트림에서 잘못되거나 손상된 데이터가 발생하며 책임감 있게 처리해야 합니다.

  • 다시 시도 및 배달 못한 편지: 임계값이 충족되면 궁극적으로 배달 못한 편지 스트림에 게시하기 전에 수많은 다시 시도를 조합하는 것은 또 다른 친숙한 방법입니다.

  • 스키마 레지스트리 사용: 스키마 레지스트리는 일관성 및 데이터 품질을 향상시키는 데 도움이 되는 사전 예방적 도구로 사용할 수 있습니다. Azure 스키마 레지스트리는 스키마가 진화함에 따라 버전 관리 및 다양한 호환성 모드와 함께 스키마 전환을 지원할 수 있습니다. 핵심적으로 스키마는 생산자와 소비자 간의 계약으로 작용하여 유효하지 않거나 손상된 데이터가 스트림에 게시될 가능성을 줄일 수 있습니다.

결국 완벽한 솔루션은 없으며 각 전략의 결과와 장단점을 철저히 검토해야 합니다. 요구 사항에 따라 이러한 기술 중 몇 가지를 함께 사용하는 것이 가장 좋은 방법일 수 있습니다.

참가자

Microsoft에서 이 문서를 유지 관리합니다. 원래 다음 기여자가 작성했습니다.

보안 주체 작성자:

비공개 LinkedIn 프로필을 보려면 LinkedIn에 로그인합니다.

다음 단계

계속하기 전에 다음 관련 문서를 검토하는 것이 좋습니다.