왜 Camel 클러스터링이 필요한가?
단일 Camel 인스턴스는 장애 발생 시 서비스가 중단됩니다. 클러스터링을 통해 여러 인스턴스를 동시에 실행하면 하나가 다운돼도 나머지가 계속 처리합니다. 하지만 모든 인스턴스가 같은 메시지를 처리하면 안 되므로 조정(coordination)이 필요합니다.
Master/Slave 패턴 – 파일 처리에서의 활용
파일 폴러처럼 오직 하나의 인스턴스만 실행해야 하는 라우트에 Master/Slave 패턴을 적용합니다. Camel의 camel-zookeeper 컴포넌트를 사용합니다.
// Master 라우트 - Zookeeper 리더 선출 통해 하나만 활성화
from("zookeeper:localhost:2181/camel/master?delay=5000&shouldReconnect=true")
.routeId("file-poller-master")
.to("direct:startFilePolling");
from("direct:startFilePolling")
.from("file:incoming?move=.done")
.to("bean:fileProcessor");
Zookeeper가 리더 선출을 관리합니다. 현재 리더가 다운되면 자동으로 다른 인스턴스가 리더가 됩니다.
여러 인스턴스 간 JMS 기반 부하 분산
JMS 큐는 본질적으로 부하 분산을 제공합니다. 여러 Camel 인스턴스가 같은 큐를 소비하면 자동으로 메시지가 분배됩니다.
// 인스턴스1과 인스턴스2가 동일한 라우트 실행
// JMS 큐가 자동으로 부하 분산
from("activemq:queue:orders?concurrentConsumers=5")
.to("bean:orderProcessor");
concurrentConsumers를 높이면 단일 인스턴스에서 멀티스레드로 처리합니다.
Camel Cluster Service – 추상화된 클러스터링
Camel 3.x부터는 ClusterService 추상화를 통해 Zookeeper, Infinispan, Kubernetes 등 여러 클러스터 백엔드를 동일한 API로 사용합니다.
// Spring Boot에서 Kubernetes 클러스터 서비스 사용
camel.cluster.kubernetes.enabled=true
camel.cluster.kubernetes.cluster-labels[app]=camel-app
// 라우트에서 클러스터 인식 적용
from("master:file-cluster:file:incoming")
.to("bean:fileProcessor");
master: 접두사를 붙이면 클러스터에서 한 인스턴스만 해당 from을 활성화합니다.
세션 스티키니스와 상태 공유
여러 인스턴스 간 상태를 공유해야 할 때는 Redis나 Infinispan 같은 분산 캐시를 활용합니다.
// Redis를 Aggregation 저장소로 사용 (클러스터 전체 공유)
from("activemq:queue:parts")
.aggregate(header("correlationId"), new MyAggregator())
.completionSize(10)
.aggregationRepository(
new RedisAggregationRepository("agg-repo", jedisPool))
.to("bean:assemblyService");
어떤 인스턴스가 다음 조각을 받아도 Redis에서 상태를 찾아 집계를 계속할 수 있습니다.