분산 아키텍처에서 시스템 간 통신은 전체 인프라의 기초를 형성합니다. 인프라의 성능, 확장성 및 신뢰성은 이벤트/메시지/데이터가 어떻게 교환되고 지속되는지에 크게 의존합니다.
Kafka와 NATS는 스트리밍 및 메시징 처리에 사용되는 두 가지 인기 있는 도구입니다. 이들은 서로 다른 아키텍처와 성능 특성을 가지고 있습니다. 특정 사용 사례에 적합합니다. 이 기사에서는 NATS의 기능을 Kafka와 비교하고 업무에서 다룬 사용 사례를 설명할 것입니다.
1. 아키텍처와 복잡성
NATS
NATS 인프라에는 두 가지 주요 구성 요소가 있습니다:
Core NATS
Core NATS는 기본 메시징 프레임워크입니다. 이는 발행-구독(Publish-Subscribe)을 지원하며(메시지를 여러 구독자에게 브로드캐스트하는 것을 허용), 요청-응답(Request-Reply)을 가능하게 하며, 큐 그룹(Queue Groups)을 사용하여 그룹 내의 여러 구독자 간 부하 분산을 용이하게 합니다.
이는 간소화, 낮은 지연 시간, 높은 성능 및 확장성을 위해 설계되었습니다. 속도와 규모가 내구성보다 중요한 시나리오에서 아주 잘 작동합니다. 그러나 Core NATS만으로는 보장되지 않는 전달만 제공하며, 이는 메시지가 활성 구독자에게만 전달되는 것을 의미합니다. 구독자가 오프라인 상태인 경우 데이터가 손실됩니다. 속도와 규모가 내구성보다 우선시되어야 하는 경우 Core NATS는 좋은 옵션입니다.
JetStream
JetStream은 Core NATS의 최상단에 지속성 기능을 제공합니다. 이는 메시지의 내구성과 신뢰성을 제공하는 데 도움이 되었습니다. 이를 통해 메시지나 이벤트를 지속(disk 또는 메모리)하고 다시 재생할 수 있습니다. 지속된 메시지는 새로운 또는 회복 중인 가입자에게 다시 재생될 수 있습니다. JetStream을 사용하면 사용자는 추가 기능을 얻게 됩니다:
- 스트림 보유 기간: 메시지를 보유하는 기간. 크기, 시간 또는 소비자 제한에 기반할 수 있습니다.
- 소비자 내구성: 소비자가 중단한 곳에서 다시 시작할 수 있도록 합니다.
- 메시지 확인: 이를 통해 전달의 신뢰성을 보장합니다.
JetStream은 Core NATS에 복잡성을 추가합니다. 그러나 이를 통해 보장된 전달, 지속성 및 재생 가능성의 사용 사례를 지원하는 중요한 기능이 제공됩니다.
Kafka
Kafka는 로그 기반 브로커 아키텍처에 구축된 분산 메시징 시스템입니다. Kafka의 데이터는 주제(Topics)로 구성되어 있으며 여러 파티션을 가질 수 있습니다. 소비자(Consumers)는 이러한 파티션에 연결됩니다. 이 아키텍처를 통해 Kafka는 단일 주제에 대한 메시지 소비를 병렬로 처리할 수 있습니다. 데이터는 주제/파티션에 순차적으로 추가됩니다. Kafka는 파티션 내에서 순서를 보장합니다. Kafka 클러스터에서는 많은 브로커가 있을 수 있으며, 각각이 토픽 및 파티션 목록을 관리합니다. 고가용성 및 데이터 손실 방지를 위해 Kafka는 파티션을 여러 Kafka 브로커에 복제하는 복제 팩터에 의존합니다. 높은 처리량, 내결함성, 데이터 보존 및 수평 확장성을 달성하기 위해 관리해야 할 여러 구성 요소가 있습니다. 이는 Kafka의 아키텍처 복잡성을 증가시킵니다.
2. 고가용성 및 성능
NATS
클러스터의 모든 노드가 망을 통해 연결되어 있으며 클라이언트는 어떤 노드에도 연결할 수 있습니다. 이 구성은 단일 장애점을 피합니다. 노드 하나가 실패하면 클라이언트는 수동 개입 없이 다른 노드에 자동으로 연결됩니다. 이를 NATS에서는 self-healing이라고 합니다. JetStream이 활성화된 노드는 스트림을 모든 노드 사이에 분배합니다. 스트림은 메시 클러스터 내의 JetStream이 활성화된 노드 사이에서 고도로 관리되고 로드 밸런싱됩니다.
JetStream은 또한 여러 클러스터 또는 노드 간 데이터 미러링을 지원합니다. JetStream에서는 스트림 당 리더가 선출됩니다. 각 스트림의 복제가 구성될 수 있습니다. 이러한 모든 사항은 NATS에서 내구성과 가용성을 보장합니다.
카프카
카프카의 높은 가용성은 복제에 기반합니다. 각 주제는 하나 이상의 파티션을 가질 수 있습니다. 각 파티션은 카프카 브로커에 걸쳐 복제됩니다. 이는 데이터 중복성과 가용성을 보장합니다. 카프카는 리더-팔로워 복제 메커니즘을 따릅니다. 리더가 읽기와 쓰기를 담당하고, 팔로워는 데이터를 복제하는 작업을 수행합니다.
카프카는 각 파티션에 대해 ISR(동기화된 복제본)을 유지합니다. 리더가 실패하면, ISR 중 하나가 리더가 됩니다. 클러스터 메타데이터 관리 및 리더 선출을 위해 카프카는 주키퍼(신버전에서는 KRaft)에 의존합니다.
Performance and Scalability
|
||
---|---|---|
특징
|
NATS
|
카프카
|
처리량
|
높은 지연 시간 또는 낮은 지연 시간. 작은 메시지에 최적화됨
|
높은 처리량과 큰 메시지에 최적화됨
|
확장성
|
클러스터링으로 수평 확장 가능
|
파티셔닝으로 수평 확장 가능
|
지연 시간
|
서브 밀리초
|
밀리초
|
Recovery and FAILOver
|
||
---|---|---|
기능
|
NATS
|
Kafka
|
장애 극복 시간
|
하위 초 (클라이언트가 더 빨리 다시 연결)
|
느림 (리더 선출 과정에 따라 다름)
|
원활한 복구
|
클라이언트가 중단 없이 자동으로 연결
|
리더 선출 중 일부 다운타임
|
데이터 손실 위험
|
복제로 최소화 (JetStream)
|
복제와 ISR 구성 시 최소화
|
3. 메시지 패턴
NATS
NATS는 주제 기반 메시징을 사용합니다. 이를 통해 서비스 및 스트림이 Pub-Sub, Request-Reply 및 Queue Subscriber 패턴을 사용할 수 있습니다. NATS의 주제는 계층 및 와일드카드로 구성할 수 있습니다. 단일 NATS 스트림은 여러 주제를 저장할 수 있으며 클라이언트 애플리케이션은 관심 있는 주제만 수신하기 위해 서버 측 필터링을 사용할 수 있습니다. NATS의 연결은 양방향이며 클라이언트가 동시에 발행 및 구독할 수 있습니다. NATS는 RabbitMQ와 매우 유사한 Queueing도 지원합니다.
Kafka
Kafka의 Streams는 Pub-sub 및 주제 기반 메시징을 지원합니다. 소비자 그룹을 통해 로드 밸런싱을 달성하고 주제를 파티션화할 수 있습니다.
4. 전달 보장
NATS
NATS는 다양한 전달 보장을 지원합니다. NATS는 최대 한 번의 전달 보장을 지원할 수 있습니다. JetStream이 활성화된 NATS 서버는 추가로 두 가지 유형의 보장을 지원할 수 있습니다. 이들은 “최소 한 번”과 “정확히 한 번”의 보장입니다. NATS는 개별 메시지에 ‘acks’를 보낼 수 있습니다. NATS가 지원하는 다양한 ‘acks’에 대해서는 NATS 공식 문서를 참조하십시오. ‘acks’ 유형에 따라 NATS는 메시지를 다시 전달할 수 있습니다.
Kafka
Kafka는 최소 한 번과 정확히 한 번의 보장을 지원합니다. 메시지 순서는 파티션 수준에서 보장됩니다. Kafka에서 전역 순서는 불가능합니다.
5. 메시지 보존 및 지속성
NATS
NATS는 메모리 및 파일 기반 지속성을 지원합니다. 메시지를 재생하는 여러 옵션이 있습니다. 메시지의 재생은 시간, 횟수 또는 순서 번호에 의해 이루어질 수 있습니다.
Kafka
KAFKA는 파일 기반의 지속성만 지원합니다. 메시지는 최신, 가장 이른 또는 특정 오프셋에서 다시 재생할 수 있습니다. KAFKA에서는 로그 압축을 지원합니다.
6. 언어 및 플랫폼
NATS
48가지 알려진 클라이언트 유형이 있습니다. GOLANG을 지원하는 아키텍처는 NATS 서버를 지원할 수 있습니다.
Kafka
18가지 알려진 클라이언트 유형이 있습니다. Kafka 서버는 JVM을 지원하는 플랫폼에서 실행할 수 있습니다.
사용 사례
사용 사례 1
요구 사항
스트리밍 파이프라인이 있는 데이터 플랫폼이 있습니다. 플랫폼은 실시간 스트리밍에 Apache Flink 엔진을 사용하고 분석 파이프라인 작성에 Apache Beam을 사용합니다. 아래는 주요 요구 사항입니다:
- 높은 처리량 및 낮은 대기 시간 메시지 처리
- 체크포인트 및 백 프레셔 처리 지원
- MB 크기의 메시지 처리
- 메시지 내구성 및 지속성
비교
Kafka 장점s:
- 높은 처리량
- 설정 가능한 보존 정책으로 데이터 보존 및 장애 허용을 위한 데이터 복제
- 최소한 하나의 메시지 전달 보장 지원
- 가장 이른/최신/특정 오프셋에서 메시지 읽기
- 신뢰할 수 있는 전달을 위한 서버 측 ‘acks’
- 대규모 데이터 스트림 및 큰 메시지 크기 처리
- Compact Topic 지원
Kafka 단점:
- 높은 리소스 사용량. 우리의 클러스터는 온프레미스이며 리소스가 제한적이었습니다
- 카프카는 거의 실시간에 가깝습니다
NATS 장점:
- 최소한의 리소스 사용으로 높은 성능을 발휘합니다. 우리의 클러스터는 리소스 제약이 있는 온프레미스 클러스터입니다
- 최소 한 번 이상을 지원합니다. 우리는 최소 한 번의 보장을 찾고 있었습니다
- 낮은 지연 시간 메시지 처리
NATS 단점:
- Flink/Beam에 대한 커넥터가 없어 통합이 어려웠습니다
- 메시지 크기에 따른 성능 저하
최종 결정
신중한 분석 후, 카프카가 선택되었습니다. 우리는 리소스 사용과 카프카가 제공하는 다른 이점, 특히 아파치 빔 및 플링크와의 좋은 통합 사이에서 균형을 맞춰야 했습니다. 카프카의 또 다른 장점은 대용량 메시지 처리와 높은 처리량을 관리하는 능력이었습니다.
사용 사례 2
요구 사항
온프레미스 클러스터에서 생성된 이벤트 처리, 예: 감사 로그. 이벤트는 낮은 지연 시간으로 처리되어야 합니다. 그리고 마이크로서비스 간의 통신을 지원해야 합니다. 내구성과 지속성은 요구 사항이 아니었습니다. 메시지 크기는 작았습니다. 이벤트에 대한 분석을 수행할 필요가 없었습니다. 우리는 제약된 환경에 있었습니다. 리소스 사용 및 메모리 풋프린트는 최소화되어야 합니다.
결정
NATS가 선택된 이유:
- 효율적인 리소스 사용
- 낮은 지연 시간 이벤트 처리.
- 고 어플리케이션인만큼 메모리 풋프린트가 매우 낮습니다
- 작은 메시지 사이즈를 처리할 수 있는 능력
- 마이크로서비스 통신을 돕는 요청-응답 지원
- JetStream이 구성되지 않은 경우 메시지가 저장되지 않습니다
Kafka가 선택되지 않은 이유:
- 기본적으로 메시지가 디스크에 저장됩니다
- 자원 사용량이 NATS와 비교했을 때 높습니다
- JVM이 필요하기 때문에 메모리 풋프린트가 매우 높습니다
요약
Kafka와 NATS 사이의 선택은 아키텍처와 복잡성, 성능 및 확장성, 메시지 전달 보장이라는 세 가지 주요 영역에 따라 특정 요구사항에 따라 달라집니다. Kafka는 견고한 이벤트 스트리밍, 내구성 있는 저장, 고급 처리 기능이 필요한 시스템에 이상적이지만 더 높은 복잡성을 가지고 있습니다. 반면 NATS는 가벼우며 관리가 쉽고, 간단한 메시징 요구를 갖는 저지연, 고처리량 시나리오에서 뛰어납니다.
분산 메시징 시스템을 설계할 때는 이러한 영역을 신중하게 평가하여 응용 프로그램의 목표와 제약 조건과 일치시키기 위해 선택해야 합니다. Kafka와 NATS는 강력한 도구이며, 올바른 선택은 사용 사례에 따라 다를 것입니다.
Kafka와 NATS 사이를 선택하기 전에 고려해야 할 주요 영역:
- 아키텍처와 복잡성
- 고 가용성과 성능
- 메시지 전달 보장
카프카는 이벤트 스트리밍, 내구성 저장 및 처리 능력을 필요로 하는 분산 시스템에 이상적입니다. 그러나 카프카는 높은 자원 사용량과 메모리 풋프린트를 가지고 있습니다. 그리고 관리 복잡성은 NATS와 비교했을 때 매우 높습니다.
반면에 NATS는 가볍고 쉽게 관리할 수 있습니다. 낮은 지연 메시지 처리는 NATS의 대표적인 능력입니다.
최종적으로, 카프카와 NATS는 강력한 이벤트 처리 도구입니다. 선택은 특정 사용 사례에 따라 다릅니다.
Source:
https://dzone.com/articles/kafka-vs-nats-message-processing