16.9 JMS 클러스터링
JBoss EAP 6의 JMS 프로바이더인 HornetQ는 클러스터링 기능과 고가용성 기능(HA)이 따로 제공되고 있다. 각각의 기능을 조합하여, 다양한 클러스터 구성이 가능하게 되었다.
HornetQ 클러스터링
HornetQ는 로드 밸런싱 기능과 HornetQ 서버로 클러스터 그룹을 구성하여 클러스터링 기능을 제공한다.
HornetQ의 로드 밸런싱은, 서버와 클라이언트에서 로드 밸런싱이 가능하다.
서버의 로드 밸런싱은 메시지 프로듀서에서 메시지 수신 시 클러스터에 포함된 다른 노드에 라운드 로빈으로 전달하여 부하를 분산한다. 다만, 로드 밸런서가 메시지를 다른 노드에 전달하여 분배 하였지만, 노드에 메시지 컨슈머가 없을 때는 메시지를 큐(Queue)에 보관한다. 이렇게 보관된 메시지를 처리하기 위해, 메시지 컨슈머가 있는 다른 클러스터 노드에 메시지를 재분배할 수도 있다.
클라이언트에서의 로드 밸런싱은 클라이언트의 접속 팩토리(ConnectionFactory)에서 만들어지는 Connection에서 클러스터에 포함된 서버들의 정보를 얻는다. 클라이언트는 서버 중 대상을 선택하여 메시지를 분산하는 방식이다. 클라이언트는 서버를 선택하는 로드 밸런싱 정책을 바꿀 수 있고, 라운드로빈(기본값)과 랜덤 방식을 사용할 수 있다.

그림 10. HornetQ 클러스터링 구성
JMS기능은 full 프로파일에서 제공한다. 또 클러스터링 기능은 ha 프로파일에서 제공한다. 따라서 JMS의 클러스터링 기능을 사용하기 위해서는 full-ha 프로파일을 사용하여야만 한다. 스탠드얼론 모드에서는 standalone-full-ha.xml 설정 파일을 사용하여 서버를 시작한다.
$./standalone.sh --server-config=standalone-full-ha.xml
이번에 설명하는 클러스터링 구성은 다음 그림과 같다. JBoss EAP 6 인스턴스에 JMS기능 을 제공하는 HornetQ가 각각 동작하고 있고, 각각의 HornetQ 서버는 로컬 디스크에 메시지를 저장한다. 앞서 메시징 서브시스템에서 설명한 것과 같이 리눅스 운영체제를 사용하는 경우는 Journal파일에 기록하는 성능을 향상하기 위해 AIO를 사용하도록 설정하는 것이 좋다.

그림11. HornetQ 클러스터링 구성
클러스터링 설정
full-ha 프로파일에서 클러스터링 기능은 clustered 속성으로 설정되어 있다.
설정 값은 다음의 CLI 명령으로 확인할 수 있다.
[standalone@localhost:9999 /] cd /subsystem=messaging/hornetq-server=default
[standalone@localhost:9999 hornetq-server=default] :read-attribute(name=clustered)
{
"outcome" => "success",
"result" => true
}
클러스터링하지 않으려면 다음 CLI 명령을 실행한다.
[standalone@localhost:9999 /] cd /subsystem=messaging/hornetq-server=default
[standalone@localhost:9999 hornetq-server=default] :write-attribute(name=clustered, value=false)
{
"outcome" => "success",
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}
클러스터를 사용하려면 먼저 cluster-password를 설정하여야 한다. 다음 CLI 명령을 사용하여 클러스터 패스워드를 설정한다. JBoss EAP 6를 설치할 때 사용했던, 관리자 패스워드를 입력한다.
따라하기
- CLI로HornetQ로 이동
- 패스워드 설정
- 리로드
- 설정값 확인
- CLI로HornetQ로 이동
[standalone@localhost:9999 /] cd /subsystem=messaging/hornetq-server=default
-
패스워드 설정
[standalone@localhost:9999 hornetq-server=default] :write-attribute(name=cluster-password, value=opennaru!234){"outcome" => "success","response-headers" => {"operation-requires-reload" => true,"process-state" => "reload-required"}} -
리로드
[standalone@localhost:9999 /] /:reload
- 설정값 확인
[standalone@localhost:9999 hornetq-server=default] :read-attribute(name=cluster-password){"outcome" => "success","result" => "opennaru!234"}
클러스터링 구성 확인
클러스터링이 정상적으로 구성되어 있는지를 CLI를 이용해 확인할 수 있다. 모든 노드를 시작하여, cluster-connection의 topology 파라미터를 참조하여 클러스터링을 구성하고 있는 멤버를 확인할 수 있다.
다음의 설정을 확인 방법에 대해 설명한다.
full-ha프로파일을 사용하는 2개의 노드(192.168.10.22,192.168.10.23)- 각각의 노드에 1개의 HornetQ 서버
cluster-connection은my-cluster(기본값)
따라하기
- CLI로 HornetQ로 이동
cluster-connection에 이동- 클러스터
connection의 topology를 확인(:read-attribute)
- CLI로 HornetQ로 이동
[standalone@localhost:9999 /] cd /subsystem=messaging/hornetq-server=default
cluster-connection에 이동
[standalone@localhost:9999 hornetq-server=default] cd cluster-connection=my-cluster
- 클러스터
connection의 topology를 확인(:read-attribute)[standalone@localhost:9999 cluster-connection=my-cluster] :read-attribute(name=topology){"outcome" => "success","result" => "topology on Topology@1b7b162[owner=ClusterConnectionImpl@4593540[nodeUUID=238320de-5aea-11e3-b75b-0b74fc5badf6, connector=TransportConfiguration(name=netty, factory=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory) ?port=5645&host=192-168-0-22, address=jms, server=HornetQServerImpl::serverUUID=238320de-5aea-11e3-b75b-0b74fc5badf6]]:238320de-5aea-11e3-b75b-0b74fc5badf6 => TopologyMember[name = undefined, connector=Pair[a=TransportConfiguration(name=netty, factory=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory)?port=5645&host=192-168-0-22, b=null]]632b962a-5739-11e3-b2f9-73f77b88aeca => TopologyMember[name = undefined, connector=Pair[a=TransportConfiguration(name=netty, factory=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory)?port=5545&host=192-168-0-23, b=null]]nodes=2 members=2"}
클러스터 연결 정보가 다음 형식으로 출력된다.
topology on Topology@1b7b162[owner=ClusterConnectionImpl@4593540[nodeUUID=238320de-5aea-11e3-b75b-0b74fc5badf6, connector=TransportConfiguration(name=netty, factory=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory) ?port=5645&host=192-168-0-22, address=jms, server=HornetQServerImpl::serverUUID=238320de-5aea-11e3-b75b-0b74fc5badf6]]:
두 번째 라 인부터 클러스터에 참가하고 있는 노드의 정보가 출력된다.
238320de-5aea-11e3-b75b-0b74fc5badf6 => TopologyMember[name = undefined, connector=Pair[a=TransportConfiguration(name=netty, factory=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory)?port=5645&host=192-168-0-22, b=null]]
여기서 a=TransportConfiguration…, b=null 형식으로 출력되는 데 a를 라이브 서버 정보, b는 백업 서버 정보를 나타낸다.
맨 마지막에 HornetQ 클러스터를 구성하고 있는 멤버 수를 표시한다. 여기서는 HornetQ 서버 수(nodes)는 2, 클러스터를 구성하고 있는 멤버 수(members)는 2개 이다.
**nodes=2 members=2"**
라이브-백업 클러스터 구성
HornetQ는 엔터프라이즈 환경에서는 반드시 필요한 신 뢰성을 구현하기 위해서 라이브-백업 구성으로 클러스터링을 구성할 수 있다. 라이브 서버는 JMS 서버로서의 실제 서비스를 제공하는 서버이다. 백업 서버는 사용되지 않고 있다가 라이브 서버에 장애가 발생할 때 사용되는 대기 상태의 서버이다. 장애 복구가 발생하면 백업 서버가 액티브 되어, 라이브 서버 대신 JMS 서버의 기능을 제공한다. 장애 복구가 발생하는 조건은 다음과 같다.
- 액티브한 라이브 서버 크래쉬
- 셧다운(셧다운을 장애 복구가 발생 시점으로 설정했을 경우)
또, 장애 복구가 발생 후, 라이브 서버를 재기동하면, 다시 원래 라이브 서버가 서비스하고 백업 서버는 대기 상태가 되는 Fail-back기능도 제공한다. HornetQ에서는 라이브 - 백업 구성 방식으로 데이터 복제와 공유 스토어를 사용하는 2가지 방식의 모드를 제공한다.

그림 12. 데이터 복제 모드
데이터 복제 모드에서는 네트워크를 통해 라이브 서버의 데이터를 백업 서버로 복제한다. 백업 서버를 시작할 때 라이브서버의 모든 데이터를 동기화해야 한다. 동기화 중에 라이브서버가 장애가 발생하면, 백업서버는 라이브 서버를 대체할 수 없게 된다.
이런 데이터 복제가 필요 없는 방식이 공유 스토어 모드이다. 라이브 서버와 백업 서버가 같은 저장소(저널 파일 시스템)를 공유하는 방식이다. 장애 시 백업 서버는 라이브 서버 대신에 JMS 서버 기능을 제공하기 위해서 공유 파일 시스템상에 저널을 그래도 사용한다. 이 방식에서는 서로 다른 서버 간에 파일 시스템을 공유할 수 있는 SAN(Storage Area Network)과 같은 공유 디바이스가 필요하다.

그림 13. 공유 스토어 모드
NFS(Network File System)등의 NAS(Network Attached Storage)는 데이터 전송 성능 문제가 있을 수 있어 추천하지 않는다. 또, 리눅스의 AIO를 사용할 경우, NFS에서 공유 스토어 모드는 정상적으로 동작하지 않는다.
또, HornetQ는 클라이언트 코드에서 자동 장애 복구 방법도 제공한다. 클라이언트 자동 장애 복구는 라이브 서버에서 장애가 발생해 액티브하게 된 백업 서버로 자동으로 재접속하여 실행 중이던 세션과 메시지 컨슈머를 자동으로 재작성해 처리하는 기능이다. 애플리케이션에서 장애시 재접속 방법을 직접 코딩할 필요가 없다.