4장 분산 메시지 큐
- 다양한 서비스에서 메시지 큐를 통해 아래와 같은 이점을 얻을 수 있다.
- 결합도 완화(decoupling): 컴포넌트 사이의 강결합을 끊을 수 있다.
- 규모 확장성: 생산자(Producer)와 소비자(Consumer)를 분리하여 규모를 확장할 수 있다.
- 가용성 개선: 특정 컴포넌트에 장애가 발생해도 다른 컴포넌트에 영향을 미치지 않는다.
- 성능 개선: 비동기 방식으로 처리할 수 있어, 서로가 서로를 기다리지 않아도 된다.
- 대표적인 분산 메시지 큐
- Kafka
- RocketMQ
- RabbitMQ
- Pulsa
- ActiveMQ
- ZeroMQ
메시지 큐 vs 이벤트 스트리밍 플랫폼
- 엄밀히 말하자면, 카프카와 펄사는 메시지 큐가 아니라 이벤트 스트리밍 플랫폼이다.
- 그러나 최근, 이 둘 사이의 경계는 흐려지고있다.
1단계: 문제 이해 및 설계 범위 확정
- 메시지 큐의 기본 기능은 간단하다.
- 생산자는 메시지를 큐에 보내고, 소비자는 큐에서 메시지를 꺼내오면 된다.
- 일반적으로 이외에 여러 가지 부가 기능을 갖는다.
- 성능 향상을 위한 여러 기능
- 메시지 전달 방식(At Least Once, At Most Once, Exactly Once)
- 데이터 보관기간 설정 등
기능 요구사항
- 생산자는 메시지 큐에 메시지를 보낼 수 있어야 한다.
- 소비자는 메시지 큐를 통해 메시지를 수신할 수 있어야 한다.
- 메시지 특성
- 크기: 수 KB 수준의 텍스트 형식
- 보관: 2주간 보관 후 삭제 가능
- 순서: 소비 순서 보장 필요
- 소비: 여러 소비자가 반복적으로 소비 가능
- 전달 방식
- 기본: 최소 한 번 전달
- 추가 지원: 최대 한 번, 정확히 한 번 전달
- 성능: 로그 수집 등 고대역폭 처리 지원 필요
비기능 요구사항
- 높은 대역폭과 낮은 전송지연 중 하나를 선택 할 수 있는 기능
- 규모 확장성: 메시지 양이 급증해도 처리가 가능해야 한다.
- 지속성 및 내구성: 데이터는 디스크에 보관되어야 하면 여러 노드에 복제되어야 한다.
전통적 메시지 큐와 다른 점
- 전통적인 메시지 큐에서는 메시지의 보관 문제를 중요하게 다루지 않는다.
- 메시지가 소비자에게 전달되기 충분한 시간동안만 보관할 뿐, 그 이상은 보관하지 않는다.
- 메시지의 전달 순서도 보장하지 않는다.
2단계: 개략적 설계안 제시 및 동의 구하기
- 생산자와 소비자는 모두 일종의 클라이언트이며, 결과적으로 메시지 큐가 일종의 서버 역할을 한다.
- 생산자는 큐에 메시지를 발행하고,
- 소비자는 큐에서 메시지를 구독한다.
메시지 모델
- 일반적으로 일대일(point to point) 또는 발행-구독(publish-subscribe) 모델을 사용한다.
일대일 모델
- 전통적인 메시지 큐에서 많이 사용되는 방식
- 하나의 메시지는 하나의 소비자에게만 전달된다.
- 이 모델은 메시지의 보관을 지원하지 않는다.
- 해당 모델에서도 보관을 지원할수는 있으나, 이는 발생-구독 모델에서 좀 더 적합하다.
Q. 일대일 모델에서 메시지의 보관을 지원은 어떻게 구현될까?
- 메시지 큐에 메시지를 전달하고, 소비자가 이를 가져가기 전까지는 당연히 메시지가 보관되어야 한다.
- 소비자가 메시지를 가져간 후에도 보관을 지원하려면 별도의 저장소가 필요하다.
- 이 때, 메시지의 복사 방식에도 즉시 복사/지연 복사 및 하이브리드 등 여러 방식이 있다.
발행-구독 모델
- 발행-구독 모델은 토픽이라는 개념을 사용한다.
- 이를 통해 여러 소비자가 동일한 메시지를 구독할 수 있다.
토픽, 파티션, 브로커
- 각 메시지는 토픽에 보관된다.
- 만약 토픽이 너무 커지면, 이를 파티션으로 나누어 관리(샤딩)한다.
- 이처럼 파티션을 유지하는 서버를 브로커라고 한다.
- 브로커를 활용하는 방식으로 높은 가용성과 확장성을 제공한다.
소비자 그룹
- 소비자 그룹은 여러 토픽을 구독할 수 있고, 각 오프셋을 관리한다.
- 이렇게 구성된 소비자 그룹이, 파티셔닝된 토픽을 구독함으로써, 대역폭을 확장 할 수 있다.
- 그러나 이로인해 메시지의 순서를 보장할수는 없게 된다.
- 하나의 제한사항을 통해 순서를 보장할 수 있는데, 이는 하나의 파티션에 하나의 소비자만을 할당하는 것이다.
- 이 경우에는, 파티션의 수가 소비자의 수보다 적어야 한다.
- 결과적으로 이는 일대일 모델에 가깝게 된다.
개략적 설계안
클라이언트
- 생산자: 메시지를 큐에 보내는 역할
- 소비자 그룹: 큐에서 메시지를 가져와서 소비한다.
핵심 서비스 및 저장소
-
브로커
- 파티션들을 유지한다.
- 하나의 파티션은 특정 토픽에 대한 부분집합이다.
-
저장소
- 데이터 저장소: 메시지를 저장한다.
- 상태 저장소: 소비자들의 상태를 저장한다.
- 메타데이터 저장소: 토픽 설정, 토픽 속성 등을 저장한다.
-
조정 서비스
- 서비스 탐색: 어떤 브로커가 살아있는지 확인한다.
- 리더 선출: 브로커들 가운데 하나의 리더를 선출하여 컨트롤러 역할을 수행한다.
- 주키퍼나 etcd가 이 역할을 수행할 수 있다.