MQTT 브로커를 사용하여 고가용성 애플리케이션 개발
Important
Azure Arc에서 사용하도록 설정된 Azure IoT Operations 미리 보기는 현재 미리 보기로 제공됩니다. 프로덕션 환경에서는 이 미리 보기 소프트웨어를 사용하면 안 됩니다.
일반적으로 사용 가능한 릴리스를 사용할 수 있게 되면 새 Azure IoT Operations 설치를 배포해야 합니다. 미리 보기 설치를 업그레이드할 수 없습니다.
베타, 미리 보기로 제공되거나 아직 일반 공급으로 릴리스되지 않은 Azure 기능에 적용되는 약관은 Microsoft Azure 미리 보기에 대한 추가 사용 약관을 참조하세요.
MQTT 브로커를 사용하여 고가용성 애플리케이션을 만들면 세션 유형, QoS(서비스 품질), 메시지 승인, 병렬 메시지 처리, 메시지 보존 및 공유 구독을 신중하게 고려해야 합니다. MQTT 브로커는 MQTT 의미 체계를 사용하여 메시지 보존 및 기본 제공 상태 관리를 제공하는 분산 메모리 내 메시지 broker 및 저장소를 제공합니다.
다음 섹션에서는 메시지 손실이 없는 강력한 분산 애플리케이션에 기여하는 설정 및 기능에 대해 설명합니다.
QoS(서비스 품질)
게시자와 구독자 모두 QoS-1을 사용하여 메시지 배달을 한 번 이상 보장해야 합니다. broker는 수신자로부터 승인(ACK)을 받을 때까지 메시지를 저장하고 다시 전송하여 전송 중에 메시지가 손실되지 않도록 합니다.
세션 유형 및 Clean-Session 플래그
메시지 손실이 없도록 하려면 MQTT 브로커에 연결할 때 clean-start 플래그를 false로 설정합니다. 이 설정은 broker에게 클라이언트에 대한 세션 상태를 유지하도록 알려, 연결 간에 구독 및 승인되지 않은 메시지를 유지합니다. 클라이언트의 연결이 끊어지고 나중에 다시 연결되면 클라이언트가 중단된 위치에서 다시 시작되어 메시지 배달 재시도를 통해 승인되지 않은 QoS-1 메시지를 수신합니다. 구성된 경우 클라이언트가 세션 만료 간격 내에 다시 연결되지 않으면 MQTT 브로커가 클라이언트 세션을 만료합니다. 기본값은 1일입니다.
다중 스레드 애플리케이션의 Receive-Max
다중 스레드 애플리케이션은 receive-max(최대 65,535)를 사용하여 메시지를 병렬로 처리하고 흐름 제어를 적용해야 합니다. 이 설정은 여러 스레드가 동시에 메시지에서 작동할 수 있도록 하고 broker가 애플리케이션 용량보다 높은 메시지 속도로 애플리케이션을 오버로드하지 않도록 하여 메시지 처리를 최적화합니다. 각 스레드는 메시지를 독립적으로 처리하고 완료 시 승인을 보낼 수 있습니다. 일반적인 방법은 애플리케이션에서 사용하는 스레드 수에 비례하여 max-receive를 구성하는 것입니다.
메시지 승인
구독자 애플리케이션이 QoS-1 메시지에 대한 승인을 보내면 메시지의 소유권을 갖습니다. QoS-1 메시지에 대한 승인을 받으면 MQTT 브로커는 해당 애플리케이션 및 토픽에 대한 메시지 추적을 중지합니다. 소유권을 적절히 이전하면 처리 문제 또는 애플리케이션 충돌 시 메시지 보존이 보장됩니다. 애플리케이션이 애플리케이션 크래시로부터 메시지를 보호하려는 경우 해당 메시지에 대한 처리를 성공적으로 완료하기 전에 애플리케이션이 소유권을 가져서는 안 됩니다. MQTT 브로커를 구독하는 애플리케이션은 최댓값이 65,535인 receive-max 값까지 처리가 완료될 때까지 메시지 승인을 지연해야 합니다. 여기에는 추가 디스패치를 위해 메시지 또는 메시지 파생물을 MQTT 브로커로 릴레이하는 것이 포함될 수 있습니다.
메시지 보존 및 broker 동작
broker는 구독자로부터 승인을 받을 때까지 메시지를 유지하여, 메시지 손실이 0이 되도록 합니다. 이 동작은 구독자 애플리케이션이 충돌하거나 일시적으로 연결이 끊어지더라도 메시지가 손실되지 않으며 애플리케이션이 다시 연결되면 처리될 수 있도록 합니다. MQTT 브로커 메시지는 Message-Expiry-Interval로 구성되고 구독자가 메시지를 소비하지 않은 경우 만료될 수 있습니다.
보존된 메시지
보존된 메시지는 특정 토픽의 최신 상태 또는 값과 같은 임시 애플리케이션 상태를 유지 관리합니다. 새 클라이언트가 토픽을 구독하면 마지막으로 보존된 메시지가 수신되어 최신 정보가 사용되도록 합니다.
Keep-Alive
연결 오류 또는 삭제 시 고가용성을 보장하려면 클라이언트-서버 통신에 적합한 keep-alive 간격을 설정합니다. 유휴 기간 동안 클라이언트는 PINGREQs를 보내면서, PINGRESPs를 기다립니다. 응답이 없으면 클라이언트에서 자동 다시 연결 논리를 구현하여 연결을 다시 설정합니다. Paho와 같은 대부분의 클라이언트에는 재시도 논리가 기본 제공되어 있습니다. MQTT 브로커는 내결함성이 있으므로 적어도 두 개의 정상 broker 인스턴스, 프런트 엔드와 백 엔드가 있을 경우 다시 연결이 성공합니다.
QoS-1 구독을 사용하는 최종 일관성
QoS-1을 사용하는 MQTT 구독은 공유 토픽을 구독하여 동일한 애플리케이션 인스턴스에서 최종 일관성을 보장합니다. 메시지가 게시되면 인스턴스는 적어도 한 번 이상 배달하여 데이터를 수신하고 복제합니다. 인스턴스는 중복을 처리하고 데이터가 동기화될 때까지 일시적인 불일치를 허용해야 합니다.
공유 구독
공유 구독을 사용하면 고가용성 애플리케이션의 여러 인스턴스에서 부하 분산을 수행할 수 있습니다. 각 구독자가 모든 메시지의 복사본을 받는 대신 메시지는 구독자 간에 고르게 분산됩니다. MQTT 브로커는 현재 애플리케이션이 스케일 아웃할 수 있도록 메시지를 배포하는 라운드 로빈 알고리즘만 지원합니다. 일반적인 사용 사례는 공유 구독에서 동일한 토픽 필터를 사용하여 모두 MQTT 브로커를 구독하는 Kubernetes ReplicaSet을 사용하여 여러 Pod를 배포하는 것입니다.
MQTT 브로커의 기본 제공 키-값 저장소(분산 HashMap) 사용
MQTT 브로커의 기본 제공 키-값 저장소는 애플리케이션 처리 상태를 관리하기 위한 간단하고 복제된 메모리 내 HashMap입니다. 예를 들어, etcd와 달리, MQTT 브로커는 메모리 내 데이터 구조, 분할 및 체인 복제를 통해 고속 처리량, 수평 크기 조정 및 짧은 대기 시간을 우선시합니다. 이를 통해 애플리케이션은 인스턴스 간에 일관된 상태에 빠르게 액세스하면서 broker의 분산 특성 및 내결함성을 사용할 수 있습니다. 분산 broker에서 제공하는 기본 제공 키-값 저장소를 사용하려면 다음을 수행합니다.
broker의 키-값 저장소 API를 사용하여 임시 스토리지 및 검색 작업을 구현하여 적절한 오류 처리 및 데이터 일관성을 보장합니다. 임시 상태는 실시간 계산 중에 중간 결과 또는 메타데이터에 빠르게 액세스하기 위해 상태 저장 처리에 사용되는 수명이 짧은 데이터 스토리지입니다. HA 애플리케이션의 컨텍스트에서 임시 상태는 충돌 간에 애플리케이션 상태를 복구하는 데 도움이 됩니다. 디스크에 쓸 수 있지만 자주 액세스하지 않는 데이터의 장기 스토리지를 위해 설계된 콜드 스토리지와는 달리 임시로 유지됩니다.
키-값 저장소를 사용하여 애플리케이션의 여러 인스턴스 간에 상태, 캐싱, 구성 또는 기타 필수 데이터를 공유하여 데이터의 일관된 보기를 유지할 수 있습니다.
MQTT 브로커의 기본 제공 Dapr 통합 사용
더 간단한 사용 사례의 경우 애플리케이션은 Dapr(Distributed Application Runtime)을 활용할 수 있습니다. Dapr은 마이크로 서비스 및 분산 애플리케이션 빌드를 간소화하는 오픈 소스의 이식 가능한 이벤트 기반 런타임입니다. 이것은 서비스 간 호출, 상태 관리 및 게시/구독 메시징과 같은 구성 요소 집합을 제공합니다.
Dapr은 MQTT 브로커의 부분으로 제공되어, MQTT 세션 관리, 메시지 QoS 및 승인, 기본 제공 키-값 저장소의 세부 정보를 추상화하여, 다음과 같은 방법으로 간단한 사용 사례에 대한 고가용성 애플리케이션을 개발할 수 있는 실용적인 선택입니다.
키-값 저장소를 처리하기 위한 상태 관리, MQTT broker와 상호 저장하기 위한 게시/구독 메시지 등과 같은 Dapr의 구성 요소를 사용하여 애플리케이션을 디자인합니다. 사용 사례에 Dapr에서 지원하지 않는 구성 요소 및 추상화가 필요하다면 앞에서 언급한 MQTT 브로커 기능을 사용하는 것이 좋습니다.
broker 및 키-값 저장소와의 원활한 통합을 위해 Dapr SDK 또는 API를 활용하여, 선호하는 프로그래밍 언어 및 프레임워크로 애플리케이션을 구현합니다.
고가용성 애플리케이션을 개발하기 위한 검사 목록
- 프로그래밍 언어에 적합한 MQTT 클라이언트 라이브러리를 선택합니다. 클라이언트는 MQTT v5를 지원해야 합니다. 애플리케이션이 대기 시간에 민감한 경우 C 또는 Rust 기반 라이브러리를 사용합니다.
- clean-session 플래그를 false로 설정하고 원하는 QoS 수준(QoS-1)을 사용하여 클라이언트 라이브러리가 MQTT 브로커에 연결하도록 구성합니다.
- 세션 만료, 메시지 만료 및 연결 유지 간격에 적합한 값을 결정합니다.
- 메시지가 성공적으로 배달되거나 처리되었을 때 승인을 보내는 것을 포함하여 구독자 애플리케이션에 대한 메시지 처리 논리를 구현합니다.
- 다중 스레드 애플리케이션의 경우 병렬 메시지 처리를 사용할 수 있도록 max-receive 매개 변수를 구성합니다.
- 보존된 메시지를 활용하여 임시 애플리케이션 상태를 유지합니다.
- MQTT 브로커의 기본 제공 키-값 저장소를 활용하여 임시 애플리케이션 상태를 관리합니다.
- 사용 사례가 간단하고 MQTT 연결 또는 메시지 처리에 대한 세부 제어가 필요하지 않은 경우 Dapr을 평가하여 애플리케이션을 개발합니다.
- 공유 구독을 구현하여 애플리케이션의 여러 인스턴스에서 고르게 메시지를 분산하여 효율적으로 크기 조정을 할 수 있도록 합니다.
예시
다음 예제에서는 고가용성 노스바운드 커넥터를 사용하여 데이터의 컨텍스트화 및 정규화를 구현합니다.
노스바운드 애플리케이션은 입력 및 출력 스테이지와 선택적 처리 스테이지로 구성됩니다. 입력 스테이지는 분산 MQTT broker를 구독하여 데이터를 수신하고 출력 스테이지는 메시지를 클라우드 데이터 레이크에 수집합니다. 처리 스테이지에서는 수신된 데이터에 대한 컨텍스트화 및 정규화 논리를 실행합니다.
고가용성을 보장하기 위해 입력 스테이지는 MQTT 브로커에 연결하고 영구 세션에 대해 clean-session 플래그를 false로 설정하여, 신뢰할 수 있는 메시지 배달을 위해 QoS-1을 사용하고, 출력 스테이지별 메시지 후처리를 승인합니다. 또한 애플리케이션은 임시 상태 관리를 위해 기본 제공 HashMap 키-값 저장소를 사용하고 라운드 로빈 알고리즘을 사용하여 공유 구독을 통해 여러 인스턴스의 부하를 분산할 수 있습니다.