태스크와 태스크가 호출하는 서비스 사이의 버퍼 역할을 하는 큐를 사용합니다. 이 방법은 서비스가 실패하거나 작업이 시간 초과될 수 있는 간헐적인 부하를 부드럽게 합니다. 이는 수요 피크가 작업 및 서비스의 가용성 및 응답성에 미치는 영향을 최소화하는 데 도움이 됩니다.
컨텍스트 및 문제점
클라우드의 많은 솔루션은 서비스를 호출하는 작업을 실행합니다. 이 환경에서는 간헐적인 부하로 인해 서비스의 성능 또는 안정성 문제가 발생할 수 있습니다.
서비스는 사용하는 작업과 동일한 솔루션의 일부이거나 자주 사용되는 리소스에 대한 액세스를 제공하는 파트너 서비스일 수 있습니다. 이러한 유형의 서비스의 예로는 캐시 또는 스토리지 서비스가 있습니다. 여러 태스크가 동시에 실행되고 동일한 서비스를 사용하는 경우 언제든지 요청 볼륨을 예측하기가 어렵습니다.
서비스는 수요 급증을 겪어 과부하가 발생할 수 있으며, 그 결과 요청에 신속하게 응답하지 못할 수 있습니다. 서비스에 많은 동시 요청을 몰아 보내면, 이러한 요청으로 인해 발생하는 경합을 처리할 수 없을 경우 서비스에 장애가 발생할 수도 있습니다.
해결 방법
작업과 서비스 사이에 큐를 배치합니다. 작업과 서비스가 비동기적으로 실행됩니다. 태스크는 서비스가 큐에 필요한 데이터를 포함하는 메시지를 게시합니다. 큐는 버퍼 역할을 하며 서비스에서 메시지를 검색할 때까지 메시지를 저장합니다. 서비스는 큐에서 메시지를 검색하고 처리합니다. 매우 가변적인 속도로 생성할 수 있는 여러 작업의 요청은 동일한 메시지 큐를 통해 서비스에 전달될 수 있습니다. 다음 다이어그램은 큐가 서비스의 부하를 평준화하는 방법을 보여줍니다.
큐는 동시 태스크가 대량의 요청을 생성하는 경우에도 서비스가 자체 속도로 메시지를 처리할 수 있도록 서비스에서 태스크를 분리합니다. 또한 큐에 메시지를 게시할 때 서비스를 사용할 수 없는 경우 작업이 지연되지 않습니다.
이 패턴은 다음과 같은 이점을 제공합니다.
서비스 지연이 애플리케이션에 즉시 직접적인 영향을 주지 않으므로 가용성을 최대화하는 데 도움이 됩니다. 서비스를 사용할 수 없거나 현재 메시지를 처리하지 않는 경우에도 애플리케이션은 큐에 메시지를 계속 게시할 수 있습니다.
큐 수와 서비스 수가 수요에 맞게 달라질 수 있으므로 확장성을 최대화하는 데 도움이 됩니다.
최대 부하가 아닌 평균 부하에 대한 요구 사항을 충족하기에 충분한 서비스 인스턴스만 필요하기 때문에 비용을 제어하는 데 도움이 됩니다.
비고
일부 서비스는 수요가 시스템 오류를 일으킬 수 있는 임계값에 도달하면 제한을 구현합니다. 스로틀링은 사용 가능한 기능을 줄일 수 있습니다. 이러한 서비스에서 부하 평준화를 구현하여 수요가 이 임계값에 도달하지 않도록 합니다.
문제 및 고려 사항
이 패턴을 구현하는 방법을 결정할 때 다음 사항을 고려합니다.
서비스가 대상 리소스를 압도하지 않도록 메시지를 처리하는 속도를 제어하는 애플리케이션 논리를 구현합니다. 요구 급증이 시스템의 다음 단계로 전달되지 않도록 합니다. 로드 중인 시스템을 테스트하여 필요한 평준화를 제공하는지 확인합니다. 필요한 평준화를 달성하려면 큐 수와 메시지를 처리하는 서비스 인스턴스 수를 조정합니다.
메시지 큐는 단방향 통신 메커니즘입니다. 태스크에 서비스에서 회신이 필요한 경우 서비스에서 응답을 보내는 데 사용할 수 있는 메커니즘을 구현해야 할 수 있습니다. 자세한 내용은 Azure의 비동기 메시징 옵션을 참조하세요.
자동 확장은 소비자들의 전체 다운스트림 처리율에 상한을 두지 않으면 과부하를 다운스트림 종속성으로 떠넘길 뿐입니다. 이 오버로드는 이러한 서비스가 공유하는 리소스에 대한 경합을 증가시키고 부하를 평준화하기 위해 큐의 효율성을 줄일 수 있습니다.
평균 생산자 비율이 소비자 비율을 초과하면 큐가 계속 증가하고 대기 시간이 증가합니다. 큐 깊이를 모니터링하고 안전한 범위 내에서 컨슈머 수를 조정하거나 프로듀서 측에서 작업을 줄이세요.
이 패턴은 메시지 손실을 방지하기 위해 큐 내구성에 따라 달라집니다. 브로커가 지속형 스토리지에 메시지를 유지하지 않는 경우 크래시 또는 용량 제한으로 인해 소비자가 데이터를 처리하기 전에 큐에 추가된 데이터가 손실될 수 있습니다. 디스크 또는 복제된 스토리지에 메시지를 보관하는 큐 서비스를 선택하고 크기 할당량 및 보존 제한을 이해합니다. 지역 오류에서 살아남기 위해 메시지가 필요한 워크로드의 경우 지역 재해 복구 옵션을 평가합니다.
대부분의 큐 서비스는 적어도 한 번 이상의 의미 체계를 사용하여 메시지를 전달합니다. 즉, 소비자가 동일한 메시지를 두 번 이상 받을 수 있습니다. 동일한 메시지를 여러 번 처리하면 동일한 결과가 생성되고 중복 레코드 또는 반복 요금과 같은 문제를 방지할 수 있도록 소비자 논리를 idempotent 로 디자인합니다.
일부 메시지는 잘못된 형식의 데이터를 포함하거나 누락된 리소스를 참조하거나 영구 오류를 트리거하기 때문에 처리할 수 없습니다. 이러한 메시지가 무기한 순환하며 큐를 차단하게 두는 대신 데드 레터 큐로 라우팅합니다. 운영 팀이 오류를 조사하고 근본 원인을 해결하며, 적절한 경우 메시지를 다시 제출할 수 있도록 데드 레터 큐 적재량을 모니터링하세요.
생산자와 소비자 간에 큐를 도입해도 모든 조건에서 원래 제출 순서가 유지되지는 않습니다. 특히 여러 소비자가 메시지를 병렬로 처리하는 경우 그렇습니다. 워크로드에 엄격한 순서 지정이 필요한 경우 Azure Service Bus message 세션 같은 기능을 사용합니다. 엄격한 순서 지정이 필요하지 않은 경우 소비자가 메시지를 순서대로 처리하도록 설계하여 크기 조정을 간소화합니다.
이 패턴을 사용하는 경우
다음과 같은 경우 이 패턴을 사용합니다.
워크로드가 간헐적으로 급증하여 다운스트림 서비스가 과부하가 될 수 있습니다.
복원력 및 비용 제어를 개선하기 위해 처리량에서 요청 유입을 분리해야 합니다.
이 패턴은 다음과 같은 경우에 적합하지 않을 수 있습니다.
호출자에는 대기 시간이 짧은 동기 응답이 필요합니다.
워크로드 볼륨은 예측 가능하게 낮고 안정적이므로 큐 복잡성을 추가하면 이점이 거의 없습니다.
워크로드 디자인
워크로드 설계에서 큐 기반 부하 수준 조정 패턴을 사용하여 Azure Well-Architected Framework 핵심 원칙에서 다루는 목표와 원칙을 해결하는 방법을 평가합니다. 다음 표에서는 이 패턴이 각 핵심 요소의 목표를 지원하는 방법에 대한 지침을 제공합니다.
| 핵심 요소 | 이 패턴으로 핵심 목표를 지원하는 방법 |
|---|---|
| 안정성 설계 결정을 통해 워크로드가 오작동에 대한 복원력을 높일 수 있으며 오류가 발생한 후 완전히 작동하는 상태로 복구 되도록 할 수 있습니다. | 이 패턴에서 설명하는 접근 방식은 작업의 도착을 처리에서 분리하여 급격한 수요 급증에 대한 복원력을 제공할 수 있습니다. 또한 큐 처리에서 오작동을 격리함으로써 입력에 영향을 주지 않도록 합니다. - RE:06 크기 조정 |
| 비용 최적화는 워크로드의 투자 수익률을 유지하고 개선하는 데 중점을 둡니다. | 부하 처리는 요청 또는 태스크 유입에서 분리되므로 이 방법을 사용하여 최대 부하를 처리하기 위해 리소스를 과도하게 프로비전할 필요성을 줄일 수 있습니다. - CO:12 크기 조정 비용 |
| 성능 효율성은 크기 조정, 데이터 및 코드의 최적화를 통해 워크로드가 수요를 효율적으로 충족 하는 데 도움이 됩니다. | 이 방법을 사용하면 요청 유입이 처리 속도와 상관 관계가 없으므로 처리량 성능을 의도적으로 디자인할 수 있습니다. - PE:05 크기 조정 및 분할 |
이 패턴이 하나의 기둥 내에서 절충을 도입하는 경우, 이를 다른 기둥의 목표와 비교해서 고려해 보세요.
예시
웹앱은 외부 데이터 저장소에 데이터를 씁니다. 웹앱의 여러 인스턴스가 동시에 실행되는 경우 데이터 저장소가 요청에 충분히 빠르게 응답하지 않아 요청 시간이 초과되거나, 제한되거나, 실패할 수 있습니다. 다음 다이어그램은 애플리케이션 인스턴스의 동시 요청에 의해 압도되는 데이터 저장소를 보여 줍니다.
이 문제를 해결하려면 큐를 사용하여 애플리케이션 인스턴스와 데이터 저장소 간의 부하를 평준화합니다. Azure Functions 앱은 Service Bus 큐에서 메시지를 읽고 데이터 저장소에 대한 읽기/쓰기 요청을 수행합니다. Azure Functions 구성된 크기 조정 범위 내에서 대상 기반 크기 조정을 사용하여 Service Bus 백로그에 따라 인스턴스 크기를 조정할 수 있습니다. 트리거 동시성 설정을 조정하여 데이터 저장소를 보호할 수도 있습니다. 구현 지침은 대상 기반 크기 조정 및 스케일 아웃 제한을 참조하세요. 이 튜닝이 없으면 작업자 계층이 백 엔드 경합을 다시 도입할 수 있습니다.
기술 변형으로 Azure Functions 대신 Azure Container Apps 사용하여 동일한 패턴을 구현할 수 있습니다. 이 접근 방식에서 컨테이너화된 작업자는 Service Bus 메시지를 사용하고 데이터 저장소에 씁니다. Container Apps는 큐 관련 크기 조정 규칙에 따라 구성된 최소 복제본과 최대 복제본 간에 작업자의 크기를 조정합니다. 이벤트 원본으로 Azure Queue Storage 사용하여 동일한 방법을 구현할 수도 있습니다. 구현 지침은 Container Apps에서 크기 조정 규칙 설정 및 Container Apps를 사용하여 이벤트 기반 작업 배포를 참조하세요.
다음 단계
다음 지침은 이 패턴을 구현할 때도 관련이 있을 수 있습니다.
Azure: 메시지 큐는 기본적으로 비동기입니다. 서비스와 직접 통신하는 경우 작업의 애플리케이션 논리를 다시 디자인해야 할 수 있습니다. 마찬가지로 메시지 큐의 요청을 수락하도록 서비스를 리팩터링해야 할 수도 있습니다. Azure 메시징 서비스 사이 선택: Azure 애플리케이션에서 메시징 및 큐 메커니즘을 선택하는 데 도움이 되는 자세한 정보를 가져옵니다.
백그라운드 작업 개발을 위한 권장 사항: 애플리케이션에서 부하가 높은 경우 메시지 큐가 백그라운드 작업에 대한 요청을 저장할 수 있도록 백그라운드 작업에 이 패턴을 적용합니다.
웹-큐-워커 아키텍처 스타일: 웹과 워커는 모두 무상태입니다. 세션 상태는 분산된 캐시에 저장할 수 있습니다. 작업자는 비동기적으로 장기 실행 작업을 수행하며 큐의 메시지에 의해 트리거되거나 일괄 처리 일정에 따라 실행할 수 있습니다.