JEUS MQ 특수 기능
본 장에서는 JEUS MQ의 특수 기능인 Message Bridge, Message Sort, Global Order, Message Group, Message Management, Topic Multicast 기능에 대해 설명한다.
1. JEUS MQ Message Bridge
Message Bridge는 두 개의 서로 다른 MQ를 연결해주는 기능으로 연결할 수 있는 서로 다른 MQ는 다음의 경우를 포함한다.
-
동일한 MQ 서비스의 다른 버전(서로 호환되지 않는 다른 버전의 JEUS MQ 간의 연결)
-
각각 다른 MQ 서비스(WebLogic 등 타 벤더의 MQ와 JEUS MQ와의 연결)
연결할 수 있는 MQ 서비스에는 제한이 없기 때문에 JEUS MQ 서비스의 동일한 버전 간에도 Message Bridge를 설정할 수 있지만 그러한 설정을 하는 것은 추천하지 않는다. JEUS MQ 서비스의 버전이 동일할 경우에는 클라이언트를 직접 원격 Destination에 붙여서 사용하는 것이 더 안전하고, 효율적이다. 굳이 동일한 버전의 JEUS MQ 서비스 간의 Bridge를 설정해야 한다면 두 JEUS MQ간의 일반적인 메시지 서비스와 구분을 위해 Bridge가 설정된 서버의 실행 스크립트에 다음의 옵션을 추가해야 한다. -Djeus.jms.client.use-single-server-entry=false |
1.1. 서버 설정
하나의 Message Bridge를 사용하려면 2가지 설정이 필요하다.
-
Message Bridge의 양끝에서 각 MQ 서비스의 연결에 대한 설정을 나타내는 Bridge Connection을 2개 설정
-
두 Bridge Connection을 연결하는 실제 Bridge를 나타내는 Bridge Entry 설정
Message Bridge는 JEUS의 MQ와는 별도로 동작하기 때문에 domain.xml의 <resources> 아래에 설정한다. 다음은 JEUS 6의 MQ로 부터 Weblogic 10.3의 MQ로의 Bridge를 설정한 예제이다.
<domain> ... <resource> <message-bridge> <bridge-connections> <connection> <name>jeus6</name> <classpath>file:///home/seunghoon/workspace/jeus6/lib/client/ clientcontainer.jar</classpath> <jndi-provider-url>127.0.0.1:19736</jndi-provider-url> <jndi-initial-context-factory>jeus.jndi.JNSContextFactory </jndi-initial-context-factory> <connection-factory>XAQueueConnectionFactory</connection-factory> <xa-support>false</xa-support> </connection> <connection> <name>weblogic103</name> <classpath> file:///home/seunghoon/bea/wlserver_10.3/server/lib/wljmsclient.jar </classpath> <jndi-provider-url>t3://localhost:7001 </jndi-provider-url> <jndi-initial-context-factory> weblogic.jndi.WLInitialContextFactory</jndi-initial-context-factory> <connection-factory>QueueConnectionFactory</connection-factory> <xa-support>false</xa-support> </connection> </bridge-connections> <bridges> <bridge> <name>bridge1</name> <source> <connection-name>jeus6</connection-name> <destination>ExamplesQueue</destination> <type>queue</type> </source> <target> <connection-name>weblogic103</connection-name> <destination>ExamplesQueue</destination> <type>queue</type> </target> </bridge> </bridges> </message-bridge> </resource> </domain>
다음은 설정 태그에 대한 설명이다. <message-bridge> 아래에 모든 설정을 할 수 있다.
-
<bridge-connection>
연결할 특정 MQ를 나타내는 설정이다.
태그 설명 <name>
해당 MQ를 대표할 이름을 설정한다.
<classpath>
해당 MQ가 제공하는 JMS 클라이언트 라이브러리의 경로를 지정한다.
<jndi-provider-url>
해당 MQ의 Destination이나 ConnectionFactory가 등록된 Naming Service에 접근할 때 필요한 Provider URL을 설정한다.
<jndi-initial-context-factory>
해당 MQ의 Destination이나 ConnectionFactory가 등록된 Naming Service에 접근할 때 필요한 Initial Context Factory의 fully qualified name을 설정한다.
<connection-factory>
해당 MQ에 접근할 때 사용할 ConnectionFactory의 이름을 설정한다.
<xa-support>
해당 MQ가 XA를 지원하는지의 여부를 설정한다. 만일 이 값을 true로 설정해두었어도 실제 ConnnectionFactory가 지원하지 않을 경우에는 XA를 사용할 수 없다.
-
<bridges><bridge>
<bridge-connection>에서 설정한 MQ들간의 연결(Bridge)을 나타내는 설정이다. 이때 하위 <bridge> 태그는 하나의 Bridge를 의미한다.
태그 설명 <name>
해당 Bridge의 이름을 나타낸다.
<source>
해당 Bridge가 메시지를 받아올 MQ와 그 MQ의 특정 Destination을 나타낸다.
-
<connection-name>: <bridge-connection>에 설정한 이름들 중 하나를 설정한다.
-
<destination>: 해당 MQ의 특정 Destination을 설정한다.
-
<type>: 해당 Destination의 타입을 설정한다. queue와 topic 중 하나를 지정할 수 있다.
<target>
해당 Bridge가 받아온 메시지를 전달할 MQ와 그 MQ의 특정 Destination을 나타낸다. 설정 방법은 <source>와 동일하다.
-
2. JEUS MQ Message Sort
어떤 큐에 메시지 송신자만 있고 수신자가 없거나 또는 수신자가 있지만 수신하는 속도가 상대적으로 느릴 때 해당 큐에는 메시지가 쌓일 수 있다. 이런 경우에 쌓이는 메시지를 사용자가 지정한 키값의 순서대로 정렬해주는 것이 Message Sort 기능이다. 큐와 마찬가지로 Durable Subscription의 경우에도 메시지가 쌓일 수 있는데 이 경우에도 Message Sort 기능을 이용할 수 있다. 지정한 키값에는 JMS의 기본적인 프로퍼티값 또는 사용자가 지정한 프로퍼티(User Property) 값들이 포함된다.
Message Sort 설정은 서버 설정 방법과 클라이언트 설정 방법이 다르다. Message Sort와 관련된 서버 설정은 domain.xml을 사용하고, 클라이언트 설정은 정렬 대상 메시지에 프로퍼티 값으로 설정한다.
2.1. 서버 설정
Message Sort 기능을 사용하려면 기준을 설정해야 한다. 이후에 Destination이나 Durable Subscription에서 위의 기준으로 만들어진 Message Sort 기능을 사용하도록 설정할 수 있다. 자세한 내용은 Destination 설정과 Durable Subscription 설정을 참고한다.
다음은 메시지 정렬 기능을 사용하기 위해서 서버에 설정한 예시이다.
<domain> ... <jms-engine> <message-sort> <name>example</name> <key>TEST</key> <type>Integer</type> <direction>ascending</direction> </message-sort> </jms-engine> <jms-resource> <destination> <type>queue</type> <name>ExamplesQueue</name> <message-sort>example</message-sort> </destination> </jms-resource> </domain>
<message-sort> 태그는 정렬의 키값이 될 프로퍼티 및 프로퍼티의 타입, 정렬의 방향 등을 설정하고, Destination이나 Durable Subscriber에 이 <message-sort>의 이름을 추가하면 해당 설정이 적용된다.
다음은 <message-sort>의 설정 태그에 대한 설명이다.
태그 | 설명 |
---|---|
<name> |
<message-sort> 설정을 나타낼 이름을 정의한다. 이 이름을 큐나 Durable Subscriber의 <message-sort> 설정에 추가하면 이 설정이 적용된다. |
<key> |
정렬의 기준이 될 키의 이름을 정의한다. |
<type> |
키값의 타입을 설정한다. Boolean, Byte, Float, Integer, Double, String을 설정할 수 있다. (기본값: String) |
<direction> |
정렬의 방향을 지정한다. ascending과 descending 중에서 설정한다. |
지정한 키값에 해당하지 않는 메시지들은 정렬의 대상이 되지 않는다. 이 경우에는 최대한 원래의 순서가 보장된다. 즉, 키값에 해당하는 메시지와 그렇지 않은 메시지들이 혼합되어서 큐에 쌓일 경우 키값에 해당하는 메시지들은 설정에 따라 정렬이 되고 그렇지 않은 메시지들은 메시지들 간의 원래의 순서가 보장된다.
3. JEUS MQ Global Order
Global Order는 Destination에 쌓인 메시지가 반드시 하나씩 클라이언트로 전달되도록 제한하여 엄격한 처리 순서를 보장하는 기능이다. 일반적인 경우에는 메시지가 여러 클라이언트에서 병렬로 처리될 가능성이 있고, 이 경우에 각각의 처리 순서는 제한할 방법이 없다. 즉, 보통의 경우 병렬로 여러 메시지 수신자를 붙이면 메시지의 처리 순서가 메시지를 송신한 순서와는 상관없이 처리된다. 이런 동작이 스펙 측면에서는 전혀 문제가 없지만, 이를 보완하여 처리 순서를 보장해야 할 필요가 있을 때 사용되는 기능이다.
3.1. 클라이언트 설정
Global Order 기능은 서버에 별다른 설정 없이 클라이언트에서 전용 API를 호출하여 사용할 수 있다.
Global Order는 메시지 수신자가 하나일 경우에는 기존과 동작의 차이가 거의 없다. 따라서 Global Order 기능을 사용할 때에는 Destination에 여러 메시지 수신자가 연결되도록 설정해야 한다. |
메시지 송신자에서 Producer를 생성한 후 JeusMessageProducer로 casting하여 전용 API를 호출한다.
JeusMessageProducer producer = (JeusMessageProducer) session.createProducer(queue); // Global Order 지정 및 이름 할당 producer.startGlobalOrder("GLOBAL-ORDER-NAME"); // 이름을 지정하지 않는 경우 //producer.startGlobalOrder();
GLOBAL-ORDER-NAME은 각 Global Order를 구별해주는 이름으로 할당하지 않는 경우 임의의 이름이 할당된다. 이후 메시지 송신은 기존과 같다. Global Order를 구별해주는 이름은 여러 클라이언트에 걸쳐서 공유하여 사용할 수 있다. 이 기능을 클러스터링과 함께 사용하면 클러스터 전체에 대해서 처리 순서를 최대한 보장한다.
4. JEUS MQ Message Group
Message Group은 특정한 목적을 가진 그룹을 설정해서 Destination에 해당 그룹에 속한 메시지가 모두 모였을 때 그 그룹의 메시지를 한 메시지 수신자에게 모두 전달하는 기능이다. 예를 들어 총 10 개짜리 크기의 그룹을 설정하면 해당 그룹에 10개의 메시지가 모두 모이기 전까지 그 메시지들은 묶인 상태로 서비스되지 않고, 10번째의 메시지가 도착하는 순간 한 메시지 수신자에게 묶음 메시지가 전달된다.
트랜잭션의 개념과 유사하며, 비슷한 용도로 사용될 수 있다. Message Group은 클러스터링과 병행하여 사용할 수 있으며, 이러한 경우에도 한 메시지 수신자에게 묶음 메시지를 전달할 수 있도록 처리해 준다.
4.1. 서버 설정
다음은 메시지 그룹 기능을 사용하기 위해서 서버에 설정한 예시이다.
<domain> ... <jms-resource> <destination> <type>queue</type> <name>ExamplesQueue</name> <message-group> <message-handling>Pass</message-handling> <expiration-time>-1</expiration-time> </message-group> </destination> </jms-resource> </domain>
<message-group> 태그는 Destination에 적용할 메시지 그룹 설정을 정의한다.
다음은 <message-group>의 설정 태그에 대한 설명이다.
태그 | 설명 |
---|---|
<message-handling> |
Destination이 메시지 그룹을 어떻게 다룰 것인지 정의한다. Pass와 Gather를 설정할 수 있다. Pass는 일반 메시지와 동일하게 취급한다. Gather는 메시지 그룹을 완성시켜서 하나의 메시지로 전달한다. |
<expiration-time> |
Destination에 완성되지 않은 메시지 그룹이 최대 얼마 동안 존재할 수 있는지 초단위로 정의한다. 기본값은 -1로, 완성될 때까지 없어지지 않는다. |
'Expiration Time'을 설정하지 않고 사용하면 완성되지 않은 Message Group은 영원히 서버에서 사라지지 않고 보관된다. 메모리의 낭비가 발생할 수 있으므로 세심한 주의가 필요하다. |
4.2. 클라이언트 설정
클라이언트 설정은 메시지 송신자와 메시지 수신자 각각의 정보를 설정해야 한다.
-
메시지 송신자 설정
메시지의 User Property를 설정하는 방법을 통해서 기능을 활성화한다.
Message msg = session.createMessage(); // Message Group 이름을 설정한다. Group을 대표하는 이름이다. msg.setStringProperty("JMS_JEUS_MSG_GROUP_NAME", "MESSAGE-GROUP-NAME"); // 해당 Group 내에서의 순서를 나타낸다. 나중에 클라이언트로 전달될 때의 순서이기도 하다. msg.setIntProperty("JMS_JEUS_MSG_GROUP_NUMBERING", 1); producer.send(msg); msg = session.createMessage(); msg.setStringProperty("JMS_JEUS_MSG_GROUP_NAME", "MESSAGE-GROUP-NAME"); msg.setIntProperty("JMS_JEUS_MSG_GROUP_NUMBERING", 2); producer.send(msg); . . . msg = session.createMessage(); msg.setStringProperty("JMS_JEUS_MSG_GROUP_NAME", "MESSAGE-GROUP-NAME"); msg.setIntProperty("JMS_JEUS_MSG_GROUP_NUMBERING", 10); // 해당 메시지가 해당 Group의 마지막 메시지임을 나타낸다. msg.setBooleanProperty("JMS_JEUS_MSG_GROUP_END", true); producer.send(msg);
-
메시지 수신자 설정
완성된 Message Group을 받으면 모든 메시지가 하나로 묶여 목록으로 이루어진 ObjectMessage로 받게 된다.
// message group으로 받는 메시지들은 하나의 ObjectMessage이고, 이 ObjectMessage는 Message들의 List이다. ObjectMessage result = (ObjectMessage) receiver.receive(TIME_OUT); List list = (List) result.getObject(); int cnt = 1; // 다음과 같이 목록에서 하나씩 꺼내와 사용할 수 있다. for(Object obj : list) { // 메시지 송신자에서 설정한 순서대로 메시지를 처리한다. TextMessage msg = (TextMessage) obj; . . . }
5. JEUS MQ Message Management 기능
Message Management 기능은 JEUS MQ를 이용해서 메시징 서비스를 사용하는 도중 Destination 내에 들어온 메시지들을 확인, 이동, 삭제 등 메시지 관리를 위해 제공되는 기능이다.
Message Management 기능은 다음과 같이 3가지로 구분된다.
-
Destination 내의 메시지를 모니터링한다.
-
메시지의 이동, 삭제, 내보내기, 가져오기를 통해 메시지를 제어한다.
-
Destination의 상세 정보를 모니터링한다.
-
원활한 메시지 모니터링과 제어 작업을 위해 Destination을 제어한다.
이때 메시지 모니터링과 메시지 제어 기능은 현재 서비스 중인 Queue나 Durable subscription에 남아 있는 메시지를 그 대상으로 하고, Destination 제어 기능은 Queue와 Topic 모두를 그 대상으로 한다.
5.1. 메시지 모니터링
Queue 또는 Durable subscription 내에 들어온 메시지를 모니터링하고 각 메시지 정보를 조회한다.
메시지 목록 조회
Queue 또는 Durable subscription 내에 남아있는 모든 메시지들의 목록을 조회하는 기능이다. 각 메시지들의 ID, 타입, 생성 시각 등의 간단한 정보를 조회하고, 조회된 목록에서 메시지를 선택해서 상세 정보 조회, 삭제, 이동, 내보내기 등의 다른 기능을 수행할 수 있다.
JMS는 메시지가 매우 빠른 속도로 생산되고 소비되기 때문에 Destination의 소비 일시중지 기능을 사용하지 않고 메시지 목록을 조회할 경우 현재 목록에는 조회된 메시지가 이미 소비되어 존재하지 않을 수 있다. |
메시지 목록 조회 과정은 다음과 같다.
-
조회할 메시지의 위치에 따라 jeusadmin의 명령어가 다음과 같이 달라진다.
-
Queue 내의 메시지
Destination 목록 조회와 관련된 명령어는 JEUS Reference 안내서의 Destination 목록 조회를 참고한다.
-
Durable subscription 내의 메시지
Durable Subscription 목록 조회와 관련된 명령어는 JEUS Reference 안내서의 Durable Subscription 목록 조회를 참고한다.
-
-
Queue 또는 Durable subscriber 내의 메시지 목록을 조회할 수 있는 기능도 있다.
메시지 목록 조회 기능을 이용할 때에는 메시지 ID나 타입, 생성 시각으로 필터링할 수도 있고, JMS 스펙에서 지정하는 Message Selector에 맞춰 특정 메시지만 선택해서 조회할 수도 있다. Queue 또는 Durable subscription 내의 모든 메시지를 조회하려면 각 파라미터를 설정하지 않은 상태로 명령어를 입력한다.
-
메시지 조회 목록에서 원하는 메시지들을 삭제, 이동, 내보내기 등의 기능을 사용할 수 있으며, 각 메시지의 상세 내용을 확인할 수도 있다.
메시지 상세 정보 조회
메시지 상세 정보 조회는 Queue 또는 Durable subscription으로 들어온 메시지의 상세 정보를 조회하는 기능이다. JMS 스펙에서 지정하는 헤더들의 모든 내용을 확인할 수 있으며 메시지의 정보와 설정된 속성들을 확인할 수있다.
JMS는 메시지가 매우 빠른 속도로 생산되고 소비되기 때문에 Destination의 소비 일시중지 기능을 사용하지 않고, 메시지 상세 정보 조회 기능을 사용할 경우 현재 목록에는 조회된 메시지가 이미 소비되어 존재하지 않을 수 있다. |
메시지 상세 정보 조회와 관련된 명령어는 JEUS Reference 안내서의 메시지 상세 정보를 참고한다.
5.2. 메시지 제어
JeusAdmin에서는 서버에 들어온 메시지에 대해 이동, 삭제, 내보내기, 가져오기와 같은 제어 기능을 제공한다.
메시지 이동
서버 또는 클러스터 내의 다른 Destination으로 메시지를 이동시킬 수 있다. 잘못된 Destination으로 메시지를 보내는 등의 실수 상황에 대처할 수 있는 유용한 기능이다.
|
메시지 이동과 관련된 명령어는 JEUS Reference 안내서의 메시지 이동을 참고한다.
'All' 옵션을 넣으면 현재 대상이 되는 Queue 또는 Durable subscriber의 모든 메시지를 대상 Destination으로 이동시킨다.
메시지 삭제
메시지 삭제는 서버 내의 메시지가 더 이상 필요하지 않게 된 경우에 사용하는 기능이다.
JMS는 메시지가 매우 빠른 속도로 생산되고 소비되기 때문에 Destination의 소비 일시중지 기능을 사용하지 않으면 메시지 목록 조회 화면에서 확인이 된 메시지여도 실제로는 이미 소비되어 삭제할 수 없는 경우가 발생할 수 있다. 따라서 정확한 메시지 삭제를 위해서는 해당 Destination이 소비 일시중지 상태에서 사용할 것을 권장한다. |
메시지 삭제와 관련된 명령어는 JEUS Reference 안내서의 메시지 삭제를 참고한다.
현재 Destination 내의 모든 메시지를 삭제하려면 'All' 옵션을 넣는다.
메시지 내보내기
Queue 또는 Durable subscriber 내의 메시지를 다른 서버나 클러스터로 옮길 수 있는 형태로 내보내는 기능이다.
JMS는 메시지가 매우 빠른 속도로 생산되고 소비되기 때문에 목록에는 조회되어도 메시지가 이미 소비되었을 수도 있다. 그러므로 원하는 메시지들을 제대로 내보내기 위해서는 Destination이 소비 일시중지 상태일 때 사용해야 한다. |
메시지 내보내기와 관련된 명령어는 JEUS Reference 안내서의 메시지 Export를 참고한다.
만약 'All' 옵션을 넣으면 해당 Destination이나 Durable subscription 내의 모든 메시지를 내보낼 수 있다. 결과적으로 메시지 내보내기가 수행되며 브라우저를 통해 "messages.xml"이라는 파일을 다운로드 받는다.
메시지 가져오기
메시지 내보내기 기능을 수행하면 생성되는 XML 파일을 이용해서 서버 내의 특정 Destination으로 메시지를 가져올 수 있다. 메시지 이동과는 달리 전혀 새로운 메시지로 취급되며, 메시지가 Destination으로 들어오는 순간 새로운 Message ID가 발급된다.
메시지 가져오기에서 'Overwrite' 항목을 체크해서 기존 메시지를 대치할 때 메시지가 이미 클라이언트로 전달되었을 가능성이 있다. 이 경우에는 가져오기는 성공하지만 덮어쓰기는 제대로 수행되지 않는다. 따라서 이 기능을 사용할 때에는 해당 Destination이 소비 일시중지 상태일 때 사용할 것을 권장한다. |
메시지 가져오기와 관련된 명령어는 JEUS Reference 안내서의 메시지 Import를 참고한다.
참고로 'Overwrite' 옵션을 넣으면 이전에 있던 메시지의 ID를 그대로 사용하고, 만약 대상이 되는 Destination 내에 같은 ID를 가진 메시지가 이미 존재한다면 그 메시지를 덮어쓴다.
5.3. Destination 모니터링
JeusAdmin에서는 다음과 같이 Destination별 상세 정보와 통계를 모니터링할 수 있다.
항목 | 설명 |
---|---|
Processed Messages |
해당 Destination에서 처리한 메시지이다. |
Remaining Messages (current) |
해당 Destination에 현재 남아있는 메시지이다. |
Remaining Messages (high mark) |
해당 Destination에 남아있는 메시지의 최대값이다. |
Pending Messages |
해당 Destination에 들어오고 아직 Receiver에게 전달되지 않은 메시지이다. Destination이 Queue일 때만 조회할 수 있다. |
Dispatched Messages |
해당 Destination에서 Receiver에게 전달 된 후 아직 응답이 돌아 오지 않은 메시지이다. Destination이 Queue일 때만 조회할 수 있다. |
Delivered Messages |
해당 Destination에 들어 온 메시지 중 Receiver로 전달이 끝난 메시지이다. |
Expired Messages |
해당 Destination에 들어 온 메시지 중 만료된 메시지이다. |
Moved Messages |
해당 Destination에서 다른 Destination으로 옮겨간 메시지이다. Destination이 Queue일 때만 조회할 수 있다. |
Removed Messages |
해당 Destination으로 들어온 메시지 중 지워진 메시지이다. Destination이 Queue일 때만 조회할 수 있다. |
Poisoned Messages |
해당 Destination으로 들어온 메시지 중 잘못 처리된 메시지이다. |
Memory Usage (current) |
해당 Destination에서 현재 사용중인 메모리 용량이다. |
Memory Usage (high mark) |
해당 Destination에서 사용한 메모리의 최대값이다. |
5.4. Destination 제어
JeusAdmin에서는 Destination별로 생산 및 소비 서비스를 일시중지하거나 재개할 수 있다.
Destination의 생산 일시중지 및 재개
해당 Destination으로 메시지를 생산하는 것을 일시중지하거나 재개하는 기능이다. Destination이 생산 일시중지 상태가 되면 해당 Destination으로 메시지를 생산하는 것이 불가능해진다.
Destination의 생산 일시중지 및 재개와 관련된 명령어는 JEUS Reference 안내서의 Destination의 상태 제어를 참고한다.
메시지 생산이 일시중지된 상태에서 Destination으로 메시지를 보낼 경우 일정 시간 기다리다가 ExceptionListener를 통해 jeus.jms.common.destination.InvalidDestinationStateException을 통보한다. |
Destination의 소비 일시중지 및 재개
해당 Destination에서 메시지 소비를 일시중지하거나 재개하는 기능이다. Destination의 소비가 일시중지 상태가 되면 해당 Destination에서 메시지를 소비하는 것이 불가능해진다.
Destination의 소비 일시중지 및 재개와 관련된 명령어는 JEUS Reference 안내서의 Destination의 상태 제어를 참고한다.
메시지 소비가 일시중지된 상태에서 Destination에서 메시지를 소비하려할 경우 해당 Destination에 메시지가 존재하지 않을 때와 동일하게 동작한다. |
6. JEUS MQ Topic Multicast
Topic Multicast는 Topic으로 들어온 메시지를 Subscriber로 보낼 때 UDP방식을 이용한 IP Multicast로 전송하는 기능이다. Multicast 방식으로 메시지를 전송하기 때문에 pub-sub 구조인 Topic을 사용할 때 성능상의 큰 이점이 있으나, UDP로 전송하는 만큼 전송의 신뢰도는 떨어질 수 있다.
Topic Multicast 기능은 IP Multicast를 사용할 수 있는 환경에서만 사용이 가능하다. IP Multicast를 사용할 수 있는 환경인지 테스트하는 방법은 JEUS Domain 안내서의 Virtual Multicast를 사용하는 도메인 생성을 참고한다.
6.1. 서버 설정
IP Mulitcast를 통해 Topic 메시지를 주고받기 위해서는 두 가지 설정이 필요하다. 먼저 서버와 클라이언트가 같은 Multicast 주소로 연결하도록 설정해야 하며, 서버에 연결된 클라이언트가 메시지를 받는 방식을 Topic Multicast로 지정하도록 설정해야 한다.
Multicast 주소는 Destination 설정에 설정하도록 되어 있다. Topic인 Destination 설정에 Multicast 주소를 포함시켜 해당 Destination을 사용하는 클라이언트에서 별도의 클라이언트 설정 없이 서버와 동일한 Multicast 주소를 통해 메시지를 받을 수 있게 되어 있다.
클라이언트가 메시지를 받는 방식을 Topic Multicast로 지정하는 설정은 ConnectionFactory에 설정하고 있다. Topic Multicast 기능을 사용하려면 Topic Multicast가 설정된 ConnectionFactory를 사용한다. 메시지를 받아오려면 Destination에 Topic Multicast 설정이 되어 있지 않다면 TCP 방식(기존 방식)으로 메시지를 받아오게 된다. 마찬가지로 Topic Multicast가 설정된 Destination에서 메시지를 받아오더라도 ConnectionFactory에 Topic Multicast 설정이 되어있지 않다면, TCP 방식으로 메시지를 받아온다. Durable subscription을 사용하는 경우 일반 Topic 메시지보다 높은 수준의 신뢰도를 요구하며, 1개의 Subscription이 동시에 1개의 클라이언트에만 메시지를 전달하기 때문에 Topic Multicast 기능을 지원하지 않는다.
7. 신뢰도 높은 메시지 송신
JEUS MQ를 이용해 메시지를 전달할 때 Persistent Store를 사용하면, 서버의 장애가 발생 했을 때에도 높은 신뢰도의 메시지 전달을 보장할 수 있다. 하지만 이것은 JEUS MQ 서버와 메시지 수신자간의 메시지 전달만을 보장하고 있으며, 메시지 송신자가 서버로 전달할 때 서버 혹은 클라이언트의 장애가 발생했을 때의 메시지 전달은 보장하지 못하고 있다.
이를 보완하기 위해서 JEUS MQ에서는 Persistence Store와 유사한 기능을 하는 JEUS의 Local Persistent Queue(이하 LPQ)를 이용하여 메시지 송신자와 JEUS MQ 서버 간의 신뢰도를 높이는 기능을 제공하고 있다. Local Persistent Queue는 데이터를 로컬의 저장소에 저장한 후, 저장된 데이터는 반드시 주어진 작업대로 처리되는 것을 보장해주는 서비스이다. JEUS MQ에서는 LPQ를 이용하여 전송하고자 하는 메시지를 전송하기 전에 저장해놓고, 메시지가 서버에 전송될 때까지 전송을 시도하여 메시지 송신자에서 서버로의 전송에 대한 신뢰도를 높이고 있다.
LPQ를 이용한 신뢰도 높은 메시지 송신은 다음과 같은 특징이 있다.
-
서버 상태에 상관없이 메시지 전송에 성공할 때까지 메시지 재전송
-
클라이언트의 상태 이상으로 전송 실패한 메시지 복구
-
비동기 메시지 전송
JMS 클라이언트가 메시지를 보낼 때 해당 클라이언트가 Jakarta EE 애플리케이션이고, 메시지를 받는 JMS 서버가 같은 해당 클라이언트가 deploy된 서버라면, 성능 향상을 위해 네트워크를 통하지 않고 메시지를 전달하기 때문에 LPQ에 관한 설정은 무시된다. |
7.1. LPQ 활성화
LPQ를 활용하여 신뢰도 높은 메시지 송신 기능을 사용하려면 먼저 LPQ를 활성화시켜야 한다. LPQ를 활성화시키는 과정은 메시지들을 저장할 저장소 생성, 메시지 처리를 위한 큐와 그리고 이들을 관리하기 위한 관리 객체 생성으로 이뤄져 있다.
LPQ를 사용하려는 stand alone 클라이언트는 실행할 때 LPQ에 관한 라이브러리와 저장소에 관한 라이브러리가 추가로 필요하다. 이들은 각각 jeus-lpq-spi.jar, jeus-lpq.jar, jms-extentsion.jar와 jeus-store.jar이며, JEUS_HOME/lib/system 폴더에 존재한다. |
LPQ를 활성화시키는 방법은 크게 3가지로 나뉜다.
-
JVM 옵션을 통한 활성화
JEUS MQ 클라이언트를 실행시킬 때에 다음과 같은 JVM옵션을 적용하여 LPQ를 활성화시킬 수 있다. 이 옵션을 사용하면 클라이언트 내에서 JMS가 Connection을 생성할 때 LPQ가 활성화된다.
-Djeus.jms.client.send-by-lpq-only=true
-
LPQ 설정 파일을 통한 활성화
JEUS MQ 클라이언트를 실행시킬 때 LPQ를 위한 설정 파일이 지정된 위치에 있다면, 해당 파일을 읽어 그 설정대로 LPQ를 활성화한다. LPQ 설정 파일의 위치와 설정 방법에 관한 더 자세한 설명은 LPQ 설정을 참고한다.
-
JEUS 전용 API를 통한 활성화
클라이언트 소스에서 JEUS 전용 세션 객체인 JeusSession으로부터 다음 API를 사용하여 LPQ를 활성화시킬 수 있다.
public void startLPQ();
|
7.2. LPQ 사용 설정
LPQ가 활성화 되었다면 메시지를 보낼 때 이를 LPQ를 통해 전송되도록 하여 메시지 송신의 신뢰도를 높일 수 있다. 이때 메시지가 LPQ를 통해 전송되도록 설정하는 단위는 다음과 같이 네가지로 나눌 수 있다.
-
JVM 단위 설정
위 LPQ 활성화 방법 중 JVM 옵션을 통해 활성화한 경우, 해당 JVM에서 보내는 모든 메시지는 LPQ를 통해 전송된다.
-
ConnectionFactory 단위 설정
JVM 옵션에 아래와 같이 LPQ를 사용할 Connection Factory 이름들을 추가하면, 해당 Connection Factory를 이용해 만들어진 Connection에서 전송되는 모든 메시지는 LPQ를 통해 보내게 된다. 각 Connection Factory의 이름은 콤마(,)로 구분한다.
jeus.jms.client.connection-factory-for-lpq=<ConnectionFactoryName1,ConnectionFactoryName2,..>
JMS 스펙 상 Connection Factory 이름에 대한 제한점은 없지만, 구분자인 콤마(,)가 들어가 있다면 위 옵션을 정상적으로 적용할 수 없어 이를 통해서는 LPQ 기능을 사용할 수 없다.
-
Session 단위 설정
Session별로 LPQ를 통해 보낼지를 지정하는 방법으로 JEUS 전용 메시지 송신자 객체의 다음 API를 사용하면, 해당 Session으로 보내는 모든 메시지를 LPQ를 통해 보낼지를 설정할 수 있다.
public void setLPQOnly(boolean lpqOnly);
-
메시지 단위 설정
메시지별로 LPQ를 통해 보낼지를 지정하는 방법으로 JEUS 전용 메시지 송신자 객체의 다음 API들을 사용하거나 메시지의 User Property를 설정하는 방법이 있다.
// JEUS 전용 API public void sendWithLPQ(Message message); public void sendWithLPQ(Message message, int deliveryMode, int priority, timeToLive); public void sendWithLPQ(Destination destination, Message message); public void sendWithLPQ(Destination destination, Message message, int deliveryMode, int priority, timeToLive); // JMS 메시지의 User Property Message msg = session.createMessage(); msg.setBooleanProperty("JMS_JEUS_USE_LPQ", true);
JEUS 전용 API를 사용하여 LPQ를 활성화하는 경우는 해당 세션에서만 LPQ를 사용할 수 있기 때문에 그 이외의 세션을 통해 보내는 메시지에는 LPQ 설정을 하더라도 무시된다.
7.3. LPQ 리스너 설정
메시지 전송에 LPQ를 사용하면 메시지가 비동기적으로 처리되어 실제 메시지가 전송되는 것을 클라이언트에서 알 수 없다. 때문에 메시지 전송의 결과와 정확한 시점을 알 수 있도록 LPQ에서는 리스너를 제공하고 있다.
리스너를 통해 메시지 전송의 결과를 받기 위해 interface로 제공되는 리스너인 jeus.jms.LPQMessageListener는 다음과 같다.
package jeus.jms; public interface LPQForwardListener { /** * 메시지의 전송이 완료되었을 때 이벤트 * @param message 전송된 메시지 */ public void onComplete(Message message); /** * 메시지의 전송 도중 Exception이 발생했을 때 이벤트 * @param message 전송하려던 메시지 * @param e 발생한 Exception */ public void onException(Message message, Exception e); /** * 메시지의 전송이 실패하였을 때 이벤트 * * @param message 전송이 실패한 메시지 * @param cause 전송이 실패한 원인 */ public void onFailure(Message message, Throwable cause); }
구현된 LPQMessageListener를 JMS 세션의 JEUS 전용 객체인 JeusSession에 다음 API를 사용하여 등록하면 메시지 전송의 결과를 제공받을 수 있다.
public void setLPQMessageListener(jeus.jms.LPQMessageListener lpqMessageListener);
또한 JEUS 전용 객체를 사용하여 LPQ를 활성화하는 경우 JeusSession의 다음 API를 사용하여 LPQ 활성화와 리스너 등록을 동시에 할 수도 있다.
public void startLPQ(jeus.jms.LPQMessageListener lpqMessageListener);
7.4. LPQ 설정
LPQ는 실패한 전송에 대한 처리, 연결이 끊어졌을 때의 동작, 저장소의 위치 또는 크기에 대한 설정들이 필요하다.
LPQ 설정 항목
다음은 LPQ 설정 항목에 대한 설명이다.
-
공통 항목
항목 타입 설명 jeus.lpq.name
String
사용하는 LPQ의 이름을 설정한다. (기본값: JEUS_LPQ)
jeus.lpq.max-message-count
int
LPQ가 한 번에 처리할 수 있는 최대 메시지 수를 설정한다. (기본값: 819200)
jeus.lpq.time-to-live
long
LPQ 내의 메시지들이 최대 얼마동안 존재할 수 있는지를 설정한다. (기본값: 43200000ms (12시간))
-
전달 관련 항목
항목 타입 설명 jeus.lpq.retry-limit
int
전달에 실패한 메시지의 재전송을 시도하는 횟수를 설정한다. 0 이하의 값으로 설정된 경우 무한히 재시도한다.
(기본값: -1)
jeus.lpq.retry-interval
long
메시지를 재전송할 때 매번 전송 시도 간 간격을 설정한다. (기본값: 1000ms)
jeus.lpq.retry-interval-increment
long
메시지를 재전송할 때 매번 전송 시도 간 간격의 증가량을 설정한다. (기본값: 0ms)
-
재연결 관련 항목
항목 타입 설명 jeus.lpq.reconnect-retry-interval
long
연결이 끊어졌을 때 재연결 시도간의 간격을 설정한다.
(기본값: 5000ms)
-
저장소 관련 항목
항목 타입 설명 jeus.lpq.store.store-mode
int
사용할 저장소의 형태를 설정한다. 1은 journal store를 사용하고 2는 메모리의 저장소를 사용한다. (기본값: 1)
jeus.lpq.store.journal.store-base-dir
String
Store를 생성할 디렉터리 이름을 설정한다. 이 디렉터리 이름은 각 LPQ 설정별로 유일해야 하며 동시의 2개 이상의 접근은 허용하지 않는다.
상대 경로로 설정되는 경우 설정 파일이 발견된 위치나 JVM이 실행된 위치의 하위로 설정된다.
(기본값: JEUS_LPQ_STORE)
jeus.lpq.store.journal.initial-log-file-count
int
Journal Store를 생성할 때 초기에 생성할 로그 파일들의 개수를 설정한다. (기본값: 2)
jeus.lpq.store.journal.max-log-file-count
int
최대로 생성할 로그 파일들의 개수를 설정한다.
(기본값: 10)
jeus.lpq.store.journal.log-file-size
String
로그 파일의 크기를 지정한다. (기본값: 64M)
Integer 타입의 값이나 숫자 뒤에 다음의 문자를 붙여 설정할 수 있다.
-
'K'(KiloBytes)
-
'M'(MegaBytes)
-
'G'(GigaBytes)
-
LPQ 설정 방법
다음은 LPQ 설정 방법에 대한 설명이다. 설정 방법 간의 우선순위는 런타임 프로퍼티 설정 > 설정 파일 > JVM 옵션 순이다.
-
설정 파일
LPQ 설정 파일이 지정된 위치에 존재한다면 LPQ가 활성화될 때 그 파일을 읽어 활성화되는 LPQ에 해당 설정을 적용시킨다. 지정된 위치는 해당 application이 설치된 위치인 DEPLOYED_HOME/myApp/WEB-INF/, DEPLOYED_HOME/myApp/META-INF/, DEPLOYED_HOME/myApp/으로 상기한 순서대로 설정 파일을 찾는다. 설정 파일의 세부 경로의 기본값은 'jeus-lpq.properties’으로 다음 옵션을 통해 변경할 수 있다.
-Djeus.jms.client.lpq-configuration-path=jeus-lpq.properties
다음은 LPQ 설정 파일의 예이다. 이 예제 파일은 JEUS_HOME/templates/lpq/에 jeus-lpq.properties라는 이름으로 제공되고 있다.
#JEUS Local-Persistent-Queue Configuration #[commons] jeus.lpq.name=JEUS_LPQ jeus.lpq.max-message-count=819200 jeus.lpq.time-to-live=43200000 #[forward] jeus.lpq.retry-limit=-1 jeus.lpq.retry-interval=1000 jeus.lpq.retry-interval-increment=0 #[reconnect] jeus.lpq.reconnect-retry-interval=5000 #[store] jeus.lpq.store.store-mode=1 #[journal-store] jeus.lpq.store.journal.store-base-dir=JEUS_LPQ jeus.lpq.store.journal.max-log-file-count=10 jeus.lpq.store.journal.initial-log-file-count=2 jeus.lpq.store.journal.log-file-size=64M
-
시스템 프로퍼티
위 설정 항목들은 각 항목명을 key로 하여 시스템 프로퍼티로도 설정할 수 있다. 예를 들어 LPQ의 이름을 설정한다면 JEUS MQ 클라이언트를 실행할 때 다음과 같이 JVM 옵션을 설정할 수 있다.
-Djeus.lpq.name=<jeus lpq name>
다음과 같이 클라이언트 소스에 코드를 추가하여 런타임에 설정을 변경할 수도 있다.
System.setProperty("jeus.lpq.name", <jeus lpq name>);