RabbitMQ 클러스터 모드
- RabbitMQ에서 장애 발생 시의 Failover 처리는 크게 **클러스터링(Clustering)**과 **Mirrored Queue(혹은 High-availbilty Queues)**의 두 가지 메커니즘으로 관리됩니다.
- RabbitMQ 클러스터 모드에서 내부 장애가 발생했을 때의 Failover 처리 방법은 RabbitMQ의 클러스터링 및 고가용성(HA) 설정에 따라 다릅니다.
- RabbitMQ 클러스터 모드는 여러 RabbitMQ 노드를 하나의 클러스터로 묶어 장애 시에도 서비스가 계속 운영될 수 있도록 설계됩니다.
1. RabbitMQ 클러스터의 구성 방식
RabbitMQ 클러스터는 Disc 노드와 RAM 노드의 조합으로 구성됩니다:
- Disc 노드: 디스크에 메타데이터(큐 정의, 사용자 정보 등)를 저장합니다. 클러스터의 주요 정보를 관리하며, 최소 1개 이상의 Disc 노드가 필요합니다.
- 메타데이터를 디스크에 저장합니다. 여기서 메타데이터는 큐 정의, 사용자 및 권한 정보, 교환기(Exchange)와 바인딩 정보 등을 포함합니다.
- 메시지의 경우, durable 및 persistent로 설정된 메시지만 디스크에 저장됩니다.
- 클러스터에서 가장 중요한 노드이며, 클러스터 내의 최소한 하나 이상의 노드는 반드시 Disc 노드여야 합니다.
- 클러스터의 데이터 일관성과 지속성을 보장합니다. 따라서 Disc 노드는 클러스터의 주요 정보를 유지 관리하고, 모든 클러스터 노드가 이 정보를 공유하도록 합니다.
- RAM 노드: 메모리에만 메타데이터를 저장합니다. 성능을 높이기 위해 사용되며, 메타데이터가 손실될 수 있습니다.
- 메타데이터를 메모리에 저장합니다. 메모리에 저장되므로 더 빠른 응답 시간과 성능을 제공합니다.
- 클러스터의 메타데이터 복제를 받지만, 노드 자체에 메타데이터를 디스크에 영구적으로 저장하지 않습니다.
- RAM 노드가 장애가 발생하면 클러스터 메타데이터를 잃을 수 있지만, Disc 노드가 여전히 살아있다면 전체 클러스터에는 큰 영향이 없습니다.
Disc 노드와 RAM 노드의 구성 전략
클러스터의 구성은 사용 사례에 따라 Disc 노드와 RAM 노드를 어떻게 배치할지 결정하는 것이 중요합니다. Disc 노드는 데이터의 안전성을 보장하고, RAM 노드는 성능을 향상시키기 위해 사용됩니다. 보통 RabbitMQ 클러스터는 다음과 같은 구성으로 관리합니다:
- 모든 노드를 Disc 노드로 구성: 메타데이터를 디스크에 저장하여 모든 노드가 장애 발생 시에도 데이터를 보존할 수 있습니다. 일반적으로 소규모 클러스터에서는 모든 노드를 Disc 노드로 설정하여 관리가 간단해집니다.
- 혼합 구성: 일부 노드는 Disc 노드로 설정하고, 다른 노드는 RAM 노드로 설정하여 메타데이터의 안정성과 클러스터 성능 간의 균형을 맞춥니다. 이는 대규모 클러스터에서 자주 사용하는 방법입니다.
RabbitMQ 클러스터 구성 예시
- 클러스터 생성:
- Disc 노드와 RAM 노드 초기화:
- 첫 번째 노드는 Disc 노드로 시작됩니다. 이 노드는 클러스터의 주요 메타데이터를 관리하게 됩니다.
# 첫 번째 노드에서 RabbitMQ 시작 (Disc 노드)
rabbitmq-server -detached
- 다른 노드를 클러스터에 추가:
- 추가적으로 노드를 클러스터에 연결합니다. 두 번째 노드를 RAM 노드로 설정할 수 있습니다.
# 두 번째 노드에서 RAM 노드로 시작
rabbitmq-server -detached
# 두 번째 노드를 첫 번째 노드의 클러스터에 RAM 노드로 추가
rabbitmqctl stop_app
rabbitmqctl join_cluster --ram rabbit@첫번째_노드의_호스트명
rabbitmqctl start_app
- 추가적인 Disc 노드 추가:
- 새로운 노드를 Disc 노드로 추가하려면 -ram 옵션 없이 join_cluster 명령을 사용합니다.
# 세 번째 노드에서 Disc 노드로 시작
rabbitmq-server -detached
# 세 번째 노드를 첫 번째 노드의 클러스터에 Disc 노드로 추가
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@첫번째_노드의_호스트명
rabbitmqctl start_app
- 클러스터 상태 확인:
rabbitmqctl cluster_status
---
Cluster status of node rabbit@node1 ...
Basics
Cluster name: rabbit@node1
Disk Nodes
rabbit@node1
rabbit@node2
RAM Nodes
rabbit@node3
Running Nodes
rabbit@node1
rabbit@node2
rabbit@node3
Versions
rabbit@node1: RabbitMQ 3.8.2 on Erlang 22.1.8
rabbit@node2: RabbitMQ 3.8.2 on Erlang 22.1.8
rabbit@node3: RabbitMQ 3.8.2 on Erlang 22.1.8
Maintenance Nodes
[]
Alarms
(none)
Network Partitions
(none)
Listeners
Node: rabbit@node1, interface: 0.0.0.0, port: 5672, protocol: amqp
Node: rabbit@node1, interface: 0.0.0.0, port: 15672, protocol: http
Node: rabbit@node2, interface: 0.0.0.0, port: 5672, protocol: amqp
Node: rabbit@node2, interface: 0.0.0.0, port: 15672, protocol: http
Node: rabbit@node3, interface: 0.0.0.0, port: 5672, protocol: amqp
Node: rabbit@node3, interface: 0.0.0.0, port: 15672, protocol: http
2. RabbitMQ 클러스터 Failover 처리 전략
RabbitMQ 클러스터링에서는 모든 노드가 클러스터 내 다른 노드들과 연결되어 있으며, 각 노드는 큐 및 메시지 메타데이터를 공유합니다. 클러스터링만을 이용하면 메시지가 자동으로 복제되지는 않으며, 메타데이터(큐 정의 등)만이 노드 간에 공유됩니다. 클러스터링에서의 장애 대응은 다음과 같이 진행됩니다:
- 노드 장애 시: 클러스터 내의 일부 노드가 장애가 발생하면, 다른 노드가 클러스터의 역할을 대신합니다. 이때, 특정 노드가 장애를 일으켜도 클러스터 내 다른 노드가 살아있다면 서비스가 계속 운영될 수 있습니다.
- 새로운 노드로의 연결: 클라이언트(Producer와 Consumer)는 장애 발생 시 다른 클러스터 노드로 연결을 시도해야 합니다. 일반적으로 이를 위한 로드 밸런서를 사용하여 자동으로 연결될 수 있도록 설정합니다.
3. Mirrored Queue (High Availability Queues)를 통한 메시지 복제 및 장애 복구
RabbitMQ에서는 Mirrored Queue를 설정하여 Failover 시 메시지의 안정성을 보장할 수 있습니다. Mirrored Queue는 하나의 Primary 노드와 여러 개의 Mirror(복제본) 노드로 구성됩니다. 이 메커니즘을 통해 노드 장애 시 메시지의 손실 없이 자동으로 Failover가 발생합니다:
- Primary 노드: 메시지를 관리하고, 클러스터 내의 Mirror 노드로 메시지를 복제합니다.
- Primary 노드는 자동으로 RabbitMQ의 클러스터 메커니즘에 의해 결정됩니다.
- 첫 번째로 Queue를 호스팅하는 노드가 Primary 노드가 됨:
- Queue가 처음 생성될 때, Queue를 처음으로 호스팅하는 노드가 Primary 노드로 지정됩니다. 이후, 정책에 따라 설정된 Mirror 노드가 생성됩니다.
- 예를 들어, rabbit@node1에서 queue1을 생성했다면, rabbit@node1이 기본적으로 queue1의 Primary 노드로 지정됩니다.
- 정책에 따라 Mirror 노드가 생성되고 Primary 노드로 승격:
- 정책(ha-policy)을 설정할 때, Mirror 노드가 특정 노드에만 생성되도록 할 수 있습니다. 이때, 자동으로 Primary 노드가 지정되며, 다른 노드가 Mirror 노드로 동작하게 됩니다.
- 클러스터의 모든 노드에 동일한 정책으로 Mirrored Queue가 생성된 경우, RabbitMQ는 자동으로 Primary 노드를 선택하여 할당합니다.
- Mirror 노드: Primary 노드의 모든 메시지를 복제하여 저장합니다. 기본적으로 클러스터의 다른 노드에서 Mirror를 유지합니다.
# 첫 번째 노드에서 RabbitMQ 서버 시작
rabbitmq-server -detached
# 두 번째 노드에서 RabbitMQ 서버 시작
rabbitmq-server -detached
# 첫 번째 노드에 두 번째 노드를 추가
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@node1
rabbitmqctl start_app
Mirrored Queue 정책 설정
클러스터가 설정되면, Mirrored Queue를 구성하기 위해 정책을 설정해야 합니다. 정책은 rabbitmqctl 명령어를 사용하거나 RabbitMQ 관리 콘솔을 통해 설정할 수 있습니다.
정책 설정 방법
- 정책을 설정하여 모든 Queue를 Mirrored Queue로 만들기:
- ha-mode가 all로 설정되면, 클러스터의 모든 Queue가 모든 노드에 복제됩니다.
- "^"는 Queue의 이름에 대한 정규 표현식이며, 모든 Queue에 적용됩니다.
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
- 특정 Queue를 Mirrored Queue로 만들기:
rabbitmqctl set_policy ha-specific "^ha\\." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
- 위 명령어는 이름이 ha.로 시작하는 Queue에 대해 아래와 같은 설정을 적용합니다:
- "ha-mode":"exactly": 특정한 수의 노드에만 복제하겠다는 설정.
- "ha-params":2: 복제본의 수를 2개로 지정 (즉, Primary를 포함하여 총 2개의 복제본).
- "ha-sync-mode":"automatic": 자동으로 Primary 노드와 Mirror 노드를 동기화.
- 정책 설정 확인:
rabbitmqctl list_policies
Mirrored Queue 테스트 및 배포
- Queue 생성 및 메시지 전송:
- Queue를 생성하고 메시지를 전송합니다. 생성된 Queue는 정책에 따라 자동으로 복제됩니다.
# Mirrored Queue 생성
rabbitmqadmin declare queue name=ha.test durable=true
# 메시지 전송
rabbitmqadmin publish routing_key=ha.test payload="Test message"
- 노드 장애 시 Failover 확인:
- Primary 노드를 종료하거나 장애를 유발시켜, Failover가 발생하는지 확인합니다.
- 관리 콘솔에서 특정 노드가 다운되더라도 다른 Mirror 노드가 새로운 Primary로 승격되는 것을 확인할 수 있습니다.
- RabbitMQ 관리 콘솔(기본 포트: 15672)에 접속하여, Queue의 상태와 복제본의 상태를 확인할 수 있습니다.
- 복제 상태 및 동기화 상태 확인:
rabbitmqctl list_queues name node
위 명령어를 통해 각 Queue가 어떤 노드에 위치하고 있는지 확인할 수 있습니다. 만약 Mirrored Queue가 제대로 설정되었다면, 각 Queue가 여러 노드에 걸쳐 복제되어 있는 것을 확인할 수 있습니다.
Failover 처리 절차
- Mirrored Queue 설정:
- Queue를 생성할 때, Mirrored Queue를 설정하여 메시지를 복제할 노드를 지정합니다. 예를 들어, RabbitMQ 정책을 통해 특정 Queue가 모든 클러스터 노드에 복제되도록 설정할 수 있습니다.
- 정책 예시:
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
-
- ha-mode는 복제 모드를 지정하며, 모든 노드에 Queue를 복제할지, 특정 노드 수를 지정할지 설정할 수 있습니다.
- Primary 노드 장애 시:
- Primary 노드가 장애가 발생하면, RabbitMQ는 자동으로 남아있는 Mirror 노드 중 하나를 새로운 Primary 노드로 승격시킵니다.
- 클러스터는 이를 자동으로 관리하며, 새로운 Primary 노드가 서비스의 메시지를 계속해서 제공할 수 있게 됩니다.
- 클라이언트 연결 재시도:
- Failover가 발생하면 클라이언트(Producer 및 Consumer)는 자동으로 새롭게 승격된 Primary 노드와 연결을 시도해야 합니다. 이를 위해 클라이언트는 RabbitMQ 노드의 IP 목록 또는 로드 밸런서를 통해 장애 복구 시 자동으로 연결을 갱신할 수 있도록 구성해야 합니다.
- 메타데이터의 일관성 보장:
- 모든 클러스터 노드가 메타데이터를 공유하므로, 새로운 Primary 노드로 전환될 때도 메타데이터의 일관성이 유지됩니다. 이를 통해 새로운 Primary 노드가 기존의 Queue와 동일한 설정을 유지할 수 있습니다.
4. RabbitMQ 클러스터링과 Mirrored Queue 설정 시의 고려사항
- 네트워크 파티션: 네트워크가 두 개 이상의 파티션으로 분리되는 상황에서는 노드 간의 연결이 끊기게 됩니다. RabbitMQ는 이러한 네트워크 분할 상태에서 오토힐 모드 또는 경쟁 방지 모드 등을 제공하여 장애를 처리합니다.
- 성능과 가용성의 균형: 모든 노드에 메시지를 복제하면 데이터의 일관성과 가용성은 높아지지만, 그만큼 네트워크 부하와 지연이 증가할 수 있습니다. 클러스터의 크기, 트래픽 양에 따라 복제 설정을 조정해야 합니다.
요약
- RabbitMQ 클러스터 모드에서는 클러스터링을 통해 메타데이터를 공유하고, Mirrored Queue를 통해 메시지를 복제하여 Failover 시 메시지의 손실을 방지합니다.
- 장애 발생 시 자동으로 Mirror 노드 중 하나가 Primary 노드로 승격되며, 클라이언트는 이를 통해 서비스의 연속성을 유지할 수 있습니다.
- 클러스터링 및 Mirrored Queue 설정을 적절히 구성하고, 로드 밸런싱을 통해 클라이언트의 연결성을 보장하는 것이 중요합니다.
'MQ' 카테고리의 다른 글
Message Queue에서 트랜잭션(Transactions) (1) | 2024.10.28 |
---|---|
RabbitMQ 메시지 패턴방식 (0) | 2024.10.20 |
MQ 과금 청구 모델 with RabbitMQ (0) | 2024.10.20 |
AMQP 프로토콜 (1) | 2024.10.20 |
Message Queue (0) | 2024.10.20 |