ActiveMQ 이중화 구성 및 성능 튜닝 전략
메시징 시스템은 분산 환경에서 시스템 간 안정적이고 빠른 데이터 전송을 위해 필수적인 요소입니다. 특히 ActiveMQ는 오픈 소스 메시지 브로커로 다양한 프로토콜과 통합 환경을 지원하며, 기업용 애플리케이션에 널리 활용되고 있습니다. 그러나 사용자 증가나 시스템 확장 시 기본 설정만으로는 한계가 발생할 수 있으므로, 이중화 구성과 세밀한 튜닝이 필요합니다. 본 포스트에서는 ActiveMQ의 이중화 구현과 성능 튜닝을 위한 구체적인 설정 방법과 코드 예시를 통해 실무에 바로 적용 가능한 가이드를 제공합니다.
1. ActiveMQ 이중화 구성의 개념과 필요성
1.1 이중화 구성의 정의
이중화 구성은 장애 발생 시 자동으로 백업 서버로 전환하여 서비스 중단 없이 운영할 수 있도록 하는 방법입니다. ActiveMQ는 주 서버와 보조 서버 간 데이터를 실시간으로 동기화하는 다양한 방법을 제공하며, 이를 통해 장애 시 빠른 복구가 가능합니다.
1.2 이중화 구성의 주요 이점
-
고가용성(HA): 단일 장애점(SPOF)을 제거하여 서비스 연속성을 보장합니다.
-
데이터 안전성: 메시지 손실 없이 데이터를 백업하여 장애 복구 시 데이터 무결성을 유지합니다.
-
확장성: 부하 증가 시 추가 서버를 통해 효율적으로 확장이 가능합니다.
2. ActiveMQ 이중화 구현 방법
ActiveMQ에서 이중화 구성은 여러 방식으로 구현할 수 있습니다. 여기서는 네트워크 클러스터링과 Master-Slave 방식의 구체적인 설정 예시를 소개합니다.
2.1 네트워크 클러스터링을 통한 이중화
네트워크 클러스터링 방식은 여러 브로커를 하나의 클러스터로 구성하여 서로 데이터를 동기화하는 방법입니다. 아래는 activemq.xml 파일 내에 네트워크 커넥터를 설정하는 예시입니다.
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="BrokerA" dataDirectory="${activemq.data}">
<!-- 네트워크 클러스터링 설정: 다른 브로커(BrokerB)와 이중화 구성 -->
<networkConnectors>
<networkConnector name="clusterConnector"
uri="static:(tcp://brokerB:61616)"
duplex="true"
timeout="3000"
updateClusterClients="true"/>
</networkConnectors>
<!-- 기타 브로커 설정 -->
</broker>
위 설정에서는 BrokerA가 BrokerB와 네트워크 커넥터를 통해 이중화 구성을 형성합니다.
-
duplex=”true” 옵션은 양방향 통신을 가능하게 하여, 어느 한쪽이 장애 시 자동으로 연결을 재설정합니다.
-
timeout 및 updateClusterClients 옵션을 통해 클러스터 환경의 안정성을 높일 수 있습니다.
또 다른 방법으로는 Master-Slave 구성을 활용할 수 있습니다. 공유 파일 시스템이나 데이터베이스를 이용해 메시지 데이터를 공유하는 방식입니다.
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="master" dataDirectory="${activemq.data}">
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>
<!-- Master-Slave 구성 설정 -->
<masterSlave>
<master/>
</masterSlave>
</broker>
보조 서버(Slave)는 master의 데이터 저장소를 공유하도록 구성되며, master에 장애가 발생하면 자동으로 slave가 활성화됩니다.
3. 사용자 증가에 따른 성능 튜닝 포인트
시스템에 사용자가 증가하면 브로커의 메시지 처리 능력과 응답 속도를 유지하기 위해 세밀한 튜닝이 필요합니다.
3.1 하드웨어 및 네트워크 최적화
CPU, 메모리, 디스크 I/O, 네트워크 대역폭 등 물리적 자원을 점검하고 최적화하여 병목 현상을 최소화합니다.
3.2 JVM 튜닝
JVM 옵션을 조정하여 Garbage Collection 효율을 높이고, 힙 메모리 크기를 상황에 맞게 설정함으로써, 애플리케이션 지연 시간과 메모리 부족 문제를 예방합니다.
3.3 ActiveMQ 설정 및 브로커 파라미터 튜닝
ActiveMQ의 성능을 극대화하기 위해 activemq.xml 내의 destinationPolicy 설정과 함께, 메시지 큐 및 토픽에 대한 세밀한 파라미터 튜닝이 중요합니다. 아래는 예시 코드입니다.
<destinationPolicy>
<policyMap>
<policyEntries>
<!-- 토픽에 대한 설정: 프로듀서 플로우 컨트롤과 메모리 제한 설정 -->
<policyEntry topic=">" producerFlowControl="true" memoryLimit="10485760" cursorMemoryHighWaterMark="70">
<pendingDurableSubscriberPolicy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingDurableSubscriberPolicy>
</policyEntry>
<!-- 큐에 대한 설정: prefetch 및 메모리 사용량 조정 -->
<policyEntry queue=">" producerFlowControl="true" memoryLimit="5242880" prefetch="50">
<pendingQueuePolicy>
<vmQueueCursor/>
</pendingQueuePolicy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
주요 파라미터 설명
- producerFlowControl: 프로듀서가 과도한 메시지 전송으로 시스템 부하를 초래하지 않도록 제어합니다.
- memoryLimit: 각 큐 또는 토픽이 사용할 수 있는 최대 메모리 용량을 제한하여, 메모리 과부하를 방지합니다.
- prefetch: 한 번에 소비자에게 전달되는 메시지 수를 제한해, 소비자가 안정적으로 처리할 수 있도록 돕습니다.
- cursorMemoryHighWaterMark: 메모리 사용량의 임계치를 설정하여, 시스템 전체의 안정적인 운영을 유지합니다.
또한, storeUsage 설정을 통해 영속 메시지 저장소의 디스크 사용량을 관리할 수 있습니다. 아래는 기본적으로 설정되어 있는 storeUsage 관련 코드입니다.
<systemUsage>
<systemUsage>
...
<storeUsage>
<storeUsage limit="100 gb"/>
</storeUsage>
...
</systemUsage>
</systemUsage>
storeUsage limit 튜닝의 주요 포인트
- 디스크 사용량 관리: 영속 메시지 저장소의 디스크 사용 한도를 적절히 조정하여, 디스크 공간 부족으로 인한 장애를 예방할 수 있습니다.
- 성능 최적화: 사용 환경에 따라 디스크 I/O 성능에 영향을 줄 수 있으므로, 필요한 경우 이 값을 상향 또는 하향 조정하여 최적의 성능을 유지합니다.
- 모니터링: 디스크 사용량을 지속적으로 모니터링하고, 임계치 도달 시 알림을 설정하는 것이 좋습니다.
관련 자료: JVM 튜닝 기법
결론
ActiveMQ의 이중화 구성과 성능 튜닝은 단순히 안정성을 확보하는 것을 넘어, 사용자 증가에 따른 부하를 효율적으로 관리하는 핵심 전략입니다. 네트워크 클러스터링이나 Master-Slave 구성 등 구체적인 설정 방법을 통해 장애에 강한 시스템을 구축하고, 큐 및 토픽에 대한 세밀한 파라미터 튜닝과 storeUsage limit 조정을 통해 최적의 성능을 유지할 수 있습니다. 이러한 전략을 통해 급격한 사용자 증가 상황에서도 원활한 메시징 서비스를 제공하며, 향후 클라우드 환경에서도 유연하게 대응할 수 있을 것입니다.
4. JDBC Persistence를 활용한 Master-Slave HA
KahaDB를 공유 파일 시스템 대신 외부 데이터베이스를 이용하면 여러 인프라 환경에서 HA를 더 유연하게 구성할 수 있습니다.
4.1 MySQL 기반 JDBC HA 구성
<!-- activemq.xml (Master/Slave 공통 설정) -->
<persistenceAdapter>
<jdbcPersistenceAdapter dataDirectory="${activemq.data}"
dataSource="#mysql-ds"
lockKeepAlivePeriod="5000"
createTablesOnStartup="true"/>
</persistenceAdapter>
<bean id="mysql-ds" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://db-vip:3306/activemq?failoverTimeout=5000"/>
<property name="username" value="activemq_user"/>
<property name="password" value="StrongPassword!"/>
<property name="maximumPoolSize" value="10"/>
<property name="minimumIdle" value="3"/>
<property name="connectionTimeout" value="3000"/>
<property name="idleTimeout" value="60000"/>
<property name="testQuery" value="SELECT 1"/>
</bean>
JDBC HA 동작 원리:
- 최초 기동 시 두 브로커가 동일 DB의
activemq_lock테이블을 경쟁적으로 획득 - 락 획득 브로커 → Master(활성), 미획득 브로커 → Slave(대기)
- Master 장애 시 DB 락이 해제되면 Slave가 락을 획득하고 Master로 승격
- 클라이언트는
failover://URL을 사용하여 자동으로 새 Master에 재연결
# 클라이언트 연결 URL (failover 설정)
failover:(tcp://broker1:61616,tcp://broker2:61616)?randomize=false&maxReconnectDelay=5000
5. ZooKeeper 기반 레플리케이션 HA (ActiveMQ Artemis)
ActiveMQ 5.x에서는 KahaDB + Shared Storage가 일반적이지만, ActiveMQ Artemis 2.x에서는 ZooKeeper 기반의 레플리케이션을 지원합니다.
5.1 ActiveMQ Artemis ZooKeeper HA 개요
[ZooKeeper Cluster]
zk1:2181 / zk2:2181 / zk3:2181
↓
[Artemis Broker 클러스터]
broker1 (Live) ←→ broker2 (Backup)
broker3 (Live) ←→ broker4 (Backup)
broker.xml (Live 브로커):
<ha-policy>
<replication>
<master>
<check-for-live-server>true</check-for-live-server>
</master>
</replication>
</ha-policy>
<cluster-connections>
<cluster-connection name="my-cluster">
<address>jms</address>
<connector-ref>netty</connector-ref>
<static-connectors>
<connector-ref>broker2-connector</connector-ref>
</static-connectors>
</cluster-connection>
</cluster-connections>
6. 페일오버 타이밍 및 장애 감지 메커니즘
6.1 장애 감지 파라미터
ActiveMQ 5.x Master-Slave 환경에서 페일오버 속도를 제어하는 주요 파라미터:
<!-- activemq.xml -->
<broker ...>
<!-- 락 유지 주기 (ms): Slave가 Master 살아있음을 확인하는 간격 -->
<persistenceAdapter>
<jdbcPersistenceAdapter lockKeepAlivePeriod="5000" .../>
</persistenceAdapter>
</broker>
클라이언트 측 failover:// URL 파라미터:
| 파라미터 | 기본값 | 설명 |
|---|---|---|
initialReconnectDelay |
10ms | 첫 재연결 시도 대기 시간 |
maxReconnectDelay |
30000ms | 최대 재연결 대기 시간 |
useExponentialBackOff |
true | 지수 백오프 재연결 |
maxReconnectAttempts |
-1 (무제한) | 최대 재연결 시도 횟수 |
randomize |
true | 랜덤 브로커 선택 여부 |
timeout |
-1 | 전체 failover 타임아웃 (-1=무제한) |
최적화된 failover URL 예시:
failover:(tcp://broker1:61616,tcp://broker2:61616)?initialReconnectDelay=100&maxReconnectDelay=5000&useExponentialBackOff=true&randomize=false
6.2 RPO/RTO 목표 설정 기준
| 구성 방식 | RTO (Recovery Time Objective) | RPO (Recovery Point Objective) |
|---|---|---|
| KahaDB + Shared NFS | 5~30초 | 0 (공유 스토리지이므로 손실 없음) |
| JDBC Persistence (MySQL HA) | 5~15초 | DB 복제 지연만큼 |
| Network of Brokers | 즉시 (라우팅 재시도) | 미전달 메시지는 재전송 |
| Artemis Replication | 1~5초 | 레플리케이션 설정에 따라 다름 |
7. 모니터링 연동 (Prometheus + Grafana)
7.1 ActiveMQ Prometheus 익스포터 설정
ActiveMQ 5.16.x 이상은 Prometheus 익스포터를 플러그인으로 지원합니다.
# Jolokia 기반 JMX Exporter 사용 방법
# 1. jmx_prometheus_javaagent 다운로드
wget https://repo.maven.apache.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.20.0/jmx_prometheus_javaagent-0.20.0.jar
# 2. activemq.conf에 JVM 옵션 추가
ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS -javaagent:/opt/activemq/lib/jmx_prometheus_javaagent-0.20.0.jar=9404:/opt/activemq/conf/prometheus-config.yaml"
prometheus-config.yaml 설정:
startDelaySeconds: 0
ssl: false
lowercaseOutputName: false
lowercaseOutputLabelNames: false
rules:
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+)><>(.+)'
name: activemq_broker_$2
labels:
broker: "$1"
- pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>(.+)'
name: activemq_queue_$3
labels:
broker: "$1"
queue: "$2"
7.2 Prometheus 수집 설정
# prometheus.yml
scrape_configs:
- job_name: 'activemq'
static_configs:
- targets: ['broker1:9404', 'broker2:9404']
scrape_interval: 30s
7.3 Grafana 대시보드 주요 패널
| 패널 | PromQL 예시 | 설명 |
|---|---|---|
| 큐 적체 메시지 수 | activemq_queue_QueueSize |
처리 대기 메시지 수 |
| 메모리 사용률 | activemq_broker_MemoryPercentUsage |
브로커 힙 메모리 사용 % |
| 저장소 사용률 | activemq_broker_StorePercentUsage |
KahaDB/JDBC 사용 % |
| 소비자 수 | activemq_queue_ConsumerCount |
각 큐의 활성 소비자 수 |
| 초당 메시지 처리 | rate(activemq_queue_EnqueueCount[1m]) |
분당 메시지 유입 속도 |
8. 재해 복구 절차 (KahaDB 백업 및 복원)
8.1 KahaDB 백업
#!/bin/bash
# ActiveMQ KahaDB 핫 백업 스크립트
# ActiveMQ가 실행 중인 상태에서도 안전하게 백업 가능
ACTIVEMQ_DATA="/opt/activemq/data/kahadb"
BACKUP_DIR="/backup/activemq/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
# KahaDB 파일 복사 (최소한의 I/O 정지로 일관성 보장)
cp -a "$ACTIVEMQ_DATA/." "$BACKUP_DIR/"
# 백업 결과 확인
ls -lh "$BACKUP_DIR"
echo "백업 완료: $BACKUP_DIR"
# 7일 이상된 백업 삭제
find /backup/activemq -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;
8.2 KahaDB 복원
#!/bin/bash
# ActiveMQ KahaDB 복원 스크립트
BACKUP_DIR="/backup/activemq/20260301_020000" # 복원할 백업 경로
ACTIVEMQ_DATA="/opt/activemq/data/kahadb"
# 1. ActiveMQ 중지
systemctl stop activemq
# 2. 현재 데이터 보관
mv "$ACTIVEMQ_DATA" "${ACTIVEMQ_DATA}.corrupted.$(date +%Y%m%d)"
# 3. 백업에서 복원
mkdir -p "$ACTIVEMQ_DATA"
cp -a "$BACKUP_DIR/." "$ACTIVEMQ_DATA/"
# 4. 권한 설정
chown -R activemq:activemq "$ACTIVEMQ_DATA"
# 5. ActiveMQ 기동
systemctl start activemq
echo "복원 완료. 서비스 상태:"
systemctl status activemq
8.3 Dead Letter Queue(DLQ) 관리
처리 실패한 메시지는 DLQ(ActiveMQ.DLQ)에 쌓입니다. 이 메시지들을 재처리하거나 정리하는 전략이 필요합니다.
<!-- DLQ 설정 세분화 (activemq.xml) -->
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry queue=">">
<deadLetterStrategy>
<!-- 큐별 전용 DLQ 사용 (DLQ.원본큐명 형태) -->
<individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true"/>
</deadLetterStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
DLQ 메시지 재처리:
# ActiveMQ 관리자 콘솔에서 DLQ 메시지를 원본 큐로 이동
# 또는 프로그램으로 재처리
# Web Console: http://localhost:8161/admin/queues.jsp
# DLQ 메시지 → Move to → 원본 큐
참고자료
-
Apache ActiveMQ 공식 문서 - http://activemq.apache.org
-
ActiveMQ 이중화 구성 사례 분석 - https://dzone.com/articles/activemq-high-availability
-
JMX 기반 ActiveMQ 모니터링 가이드 - https://www.baeldung.com/java-monitoring-jmx
-
JVM 튜닝 기법 - https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
-
대규모 메시징 시스템 구축 사례 - https://dzone.com/articles/messaging-systems-best-practices
-
Apache ActiveMQ 릴리즈 노트 - http://activemq.apache.org/components/artemis/documentation/
-
https://pridebj88.tistory.com/2
댓글남기기