내용 목차
본 장에서는 JEUS MQ의 특수 기능인 Message Bridge, Message Sort, Global Order, Message Group, Message Management 기능에 대해 설명한다.
Message Bridge는 두 개의 서로 다른 MQ를 연결해주는 기능으로 연결할 수 있는 서로 다른 MQ는 다음의 경우를 포함한다.
동일한 MQ 서비스의 다른 버전(서로 호환되지 않는 다른 버전의 JEUS MQ 간의 연결)
각각 다른 MQ 서비스(WebLogic 등 타 벤더의 MQ와 JEUS MQ와의 연결)
[주의사항]
연결할 수 있는 MQ 서비스에는 제한이 없기 때문에 JEUS MQ 서비스의 동일한 버전 간에도 Message Bridge를 설정할 수 있지만 그러한 설정을 하는 것은 추천하지 않는다.
JEUS MQ 서비스의 버전이 동일할 경우에는 클라이언트를 직접 원격 Destination에 붙여서 사용하는 것이 더 안전하고, 효율적이다. 굳이 동일한 버전의 JEUS MQ 서비스 간의 Bridge를 설정해야 한다면 Bridge가 설정된 서버의 실행 스크립트에 다음의 옵션을 추가해야 한다.
-Djeus.jms.client.use-single-server-entry=false
하나의 Message Bridge를 사용하려면 2가지 설정이 필요하다.
Message Bridge의 양끝에서 각 MQ 서비스의 연결에 대한 설정을 나타내는 Bridge Connection을 2개 설정
두 Bridge Connection을 연결하는 실제 Bridge를 나타내는 Bridge Entry 설정
다음은 WebAdmin의 MQ로부터 WebLogic 10.3의 MQ로의 Bridge를 설정한 예제 화면이다.
Message Bridge는 JEUS의 MQ와는 별도로 동작하기 때문에 해당 설정은 WebAdmin 완쪽 메뉴에 [Resources] > [Message Bridge]를 선택한다.
Message Connections 영역에 MQ와 WebLogic 10.3의 MQ에 대한 설정을 하고, Message Entries에 이 둘 사이의 연결을 설정한다. Message Connection이나 Message Entry의 세부 항목을 설정하려면 설정하려는 항목의 이름을 클릭한다. 다음과 같이 세부 항목 설정 화면으로 이동하면 각 항목의 정보를 설정하고 [확인] 버튼을 클릭하면 설정한 정보가 저장된다. 항목을 다시 설정하려면 [재설정] 버튼을 클릭한다.
각 세부 항목 설정 화면은 다음과 같다.
어떤 큐에 메시지 송신자만 있고 수신자가 없거나 또는 수신자가 있지만 수신하는 속도가 상대적으로 느릴 때 해당 큐에는 메시지가 쌓일 수 있다. 이런 경우에 쌓이는 메시지를 사용자가 지정한 키값의 순서대로 정렬해주는 것이 Message Sort 기능이다.
큐와 마찬가지로 Durable Subscriber의 경우에도 메시지가 쌓일 수 있는데 이 경우에도 Message Sort 기능을 이용할 수 있다. 지정한 키 값에는 JMS의 기본적인 프로퍼티값 또는 사용자가 지정한 프로퍼티(User Property)값들이 포함된다.
Message Sort 설정은 서버 설정 방법과 클라이언트 설정 방법이 다르다. Message Sort와 관련된 서버 설정은 WebAdmin을 사용하고, 클라이언트 설정은 정렬 대상 메시지에 프로퍼티값으로 설정한다.
서버의 Message Sort 설정은 WebAdmin의 [Server] > [서버 선택] > [Engine] > [Jms Engine] > [Message Sort] 메뉴를 선택한다.
Message Sort 기능을 사용하려면 서버에 다음과 같이 기준을 설정해야 한다.
이후에 다음과 같이 Destinaition이나 Durable Subscriber에서 위의 기준으로 만들어진 Message Sort 기능을 사용하도록 설정할 수 있다. 자세한 내용은 “3.2.1. Destination 설정”과 “3.2.2. Durable Subscriber 설정”을 참고한다.
지정한 키값에 해당하지 않는 메시지들은 정렬의 대상이 되지 않는다. 이 경우에는 최대한 원래의 순서가 보장된다. 즉, 키값에 해당하는 메시지와 그렇지 않은 메시지들이 혼합되어서 큐에 쌓일 경우 키값에 해당하는 메시지들은 설정에 따라 정렬이 되고 그렇지 않은 메시지들은 메시지들 간의 원래의 순서가 보장된다.
Global Order는 Destination에 쌓인 메시지가 반드시 하나씩 클라이언트로 전달되도록 제한하여 엄격한 처리 순서를 보장하는 기능이다.
일반적인 경우에는 메시지가 여러 클라이언트에서 병렬로 처리될 가능성이 있고, 이 경우에 각각의 처리 순서는 제한할 방법이 없다. 즉, 보통의 경우 병렬로 여러 메시지 수신자를 붙이면 메시지의 처리 순서가 메시지를 송신한 순서와는 상관없이 처리된다. 이런 동작이 스펙 측면에서는 전혀 문제가 없지만, 이를 보완하여 처리 순서를 보장해야 할 필요가 있을 때 사용되는 기능이다.
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를 구별해주는 이름은 여러 클라이언트에 걸쳐서 공유하여 사용할 수 있다. 이 기능을 클러스터링과 함께 사용하면 클러스터 전체에 대해서 처리 순서를 최대한 보장한다.
Message Group은 특정한 목적을 가진 그룹을 설정해서 Destination에 해당 그룹에 속한 메시지가 모두 모였을 때 그 그룹의 메시지를 한 메시지 수신자에게 모두 전달하는 기능이다. 예를 들어 총 10 개짜리 크기의 그룹을 설정하면 해당 그룹에 10개의 메시지가 모두 모이기 전까지 그 메시지들은 묶인 상태로 서비스되지 않고, 10번째의 메시지가 도착하는 순간 한 메시지 수신자에게 묶음 메시지가 전달된다. 트랜잭션의 개념과 유사하며, 비슷한 용도로 사용될 수 있다.
Message Group은 클러스터링과 병행하여 사용할 수 있으며, 이러한 경우에도 한 메시지 수신자에게 묶음 메시지를 전달할 수 있도록 처리해준다.
Message Group 기능을 사용하기 위해 필요한 서버 설정들에 대해서 설명한다. Message Group은 Destination 설정 화면에서 추가로 설정한다. Destination 설정 화면에 대한 자세한 내용은 “3.2.1. Destination 설정”을 참고한다.
'Expiration Time'을 설정하지 않고 사용하면 완성되지 않은 Message Group은 영원히 서버에서 사라지지 않고 보관된다. 메모리의 낭비가 발생할 수 있으므로 세심한 주의가 필요하다.
클라이언트 설정은 메시지 송신자와 메시지 수신자 각각의 정보를 설정해야 한다.
메시지 송신자 설정
메시지의 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; . . . }
Message Management 기능은 JEUS MQ를 이용해서 메시징 서비스를 사용하는 도중 Destination 내에 들어온 메시지들을 확인, 이동, 삭제 등 메시지 관리를 위해 제공되는 기능이다.
Message Management 기능은 다음과 같이 3가지로 구분된다.
Destination 내의 메시지를 모니터링한다.
메시지의 이동, 삭제, 내보내기, 가져오기를 통해 메시지를 제어한다.
원활한 메시지 모니터링과 제어 작업을 위해 Destination을 제어한다.
이때 메시지 모니터링과 메시지 제어 기능은 현재 서비스 중인 Queue나 Durable subscriber에 남아 있는 메시지를 그 대상으로 하고, Destination 제어 기능은 Queue와 Topic 모두를 그 대상으로 한다.
Queue 또는 Durable subscriber 내에 들어온 메시지의 목록을 조회하고 각 메시지의 상세정보를 조회한다.
Queue 또는 Durable subscriber 내에 남아있는 모든 메시지들의 목록을 조회하는 기능이다. 각 메시지들의 ID, 타입, 생성 시각 등의 간단한 정보를 조회하고, 조회된 목록에서 메시지를 선택해서 상세 정보 조회, 삭제, 이동, 내보내기 등의 다른 기능을 수행할 수 있다.
메시지 목록 조회 과정은 다음과 같다.
조회할 메시지의 위치에 따라 WebAdmin에서의 메뉴가 다음과 같이 달라진다.
Queue 내의 메시지
[Monitoring] > [JMS] 메뉴를 선택하고 [Destinations] 탭의 [Server]를 선택한다. 메시지를 조회할 서버를 선택하면 해당 서버 내의 Destination 목록이 조회된다.
Durable subscriber 내의 메시지
[Monitoring] > [JMS] 메뉴를 선택하고 [Durable Subscriptions] 탭의 [Server]를 선택한다. 메시지를 조회할 서버를 선택하면 해당 서버 내의 Durable Subscription 목록이 조회된다.
조회할 Queue 또는 Durable subscription의 [browse] 버튼을 클릭하면 선택한 Queue 또는 Durable subscriber 내의 메시지 목록을 조회하기 위한 Message List 화면 이 나타난다.
메시지 목록 조회 기능을 이용할 때에는 메시지 ID나 타입, 생성 시각으로 필터링할 수도 있고, JMS 스펙에서 지정하는 Message Selector에 맞춰 특정 메시지만 선택해서 조회할 수도 있다. Queue 또는 Durable subscription 내의 모든 메시지를 조회하려면 각 항목을 설정하지 않은 상태로 [확인] 버튼을 클릭한다.
다음은 Destination 내의 메시지 조회 목록이다. 이때 각 메시지 앞의 체크박스를 체크해서 원하는 메시지들을 삭제, 이동, 내보내기 등의 기능을 사용할 수 있으며, 'Message ID' 컬럼의 메시지 ID를 클릭해서 메시지의 상세 내용을 확인할 수 있다.
JMS는 메시지가 매우 빠른 속도로 생산되고 소비되기 때문에 Destination의 소비 일시중지 기능을 사용하지 않고 메시지 목록을 조회할 경우 현재 목록에는 조회된 메시지가 이미 소비되어 존재하지 않을 수 있다.
JMS 스펙에서 지정하는 헤더들의 모든 내용을 확인할 수 있으며 Queue 또는 Durable subscriber로 들어온 메시지의 정보와 설정된 속성들을 확인할 수있다.
메시지 상세 정보 조회 방법은 다음과 같다.
조회된 메시지 목록에서 특정 'Message ID'를 클릭하면 메시지의 상세 정보를 확인할 수 있다.
상세 정보 화면에서 일부 헤더들과 메시지의 타입이 'Text'일 때의 메시지의 내용, 메시지 프로퍼티들은 수정할 수 있다. 수정할 항목을 변경하고 [확인] 버튼을 클릭하면 메시지 정보가 수정된다.
[재설정] 버튼을 클릭하면 수정되었던 내용이 원래 상태로 복구된다.
JMS는 메시지가 매우 빠른 속도로 생산되고 소비되기 때문에 Destination의 소비 일시중지 기능을 사용하지 않고, 메시지 상세 정보 조회 기능을 사용할 경우 현재 목록에는 조회된 메시지가 이미 소비되어 존재하지 않을 수 있다. 특히 메시지 정보를 수정할 때 일시중지 상태가 아니라면 메시지 정보 수정에 대해 보장할 수 없다.
WebAdmin의 [Monitoring] > [JMS] 메뉴를 선택하고 [Destinations] 탭의 [Server]를 선택하면 Destination 화면으로 이동한다. 해당 화면에서 서버에 들어온 메시지들에 대해 이동, 삭제, 내보내기, 가져오기와 같은 제어 기능을 제공한다.
서버 또는 클러스터 내의 다른 Destination으로 메시지를 이동시킬 수 있다. 잘못된 Destination으로 메시지를 보내는 등의 실수 상황에 대처할 수 있는 유용한 기능이다.
메시지 이동 과정은 다음과 같다.
Destination 화면([그림 6.14])에서 이동할 메시지를 체크하고 [move] 버튼을 클릭한다.
Move Message 화면의 'Target' 항목에 대상이 되는 Destination을 선택할 수 있다. 또한 'All'을 체크하면 현재 선택된 Queue 또는 Durable subscriber의 모든 메시지를 대상 Destination으로 이동시킨다. 각 항목을 설정하고 [확인] 버튼을 클릭하면 선택한 메시지가 설정에 따라 이동된다.
1. JMS는 메시지가 매우 빠른 속도로 생산되고 소비되기 때문에 원본 메시지가 존재하는 Destination의 소비 일시중지 기능을 사용하지 않을 경우 이동시킬 메시지가 이미 해당 Destination에 존재하지 않을 수 있다.
2. 메시지 이동은 메시지를 그대로 다른 Destination에 옮기는 기능이다. 만약 대상 Destination에 이동시킬 메시지와 같은 ID를 가진 메시지가 이미 존재한다면 이동할 메시지가 이전 메시지를 덮어쓴다. 대상 Destination에서 같은 ID를 가진 메시지가 존재해서 덮어쓰려 할 때 해당 메시지가 이미 클라이언트로 전달되었다면 서버와 클라이언트 간에 메시지가 서로 맞지 않는 상황이 발생할 수 있다. 그러므로 메시지를 이동시킬 때에는 두 Destination이 모두 소비 일시중지 상태인 경우에 사용할 것을 권장한다.
메시지 삭제는 서버 내의 메시지가 더 이상 필요하지 않게 된 경우에 사용하는 기능이다.
메시지 삭제 과정은 다음과 같다.
Destination 화면([그림 6.14])에서 삭제할 메시지를 체크하고 [remove] 버튼을 클릭한다.
Remove Message 화면에서 [확인] 버튼을 클릭하면 선택된 메시지를 서버에서 삭제한다. 현재 Destination 내의 모든 메시지를 삭제하려면 'All'을 체크하고 [확인] 버튼을 클릭한다.
JMS는 메시지가 매우 빠른 속도로 생산되고 소비되기 때문에 Destination의 소비 일시중지 기능을 사용하지 않으면 메시지 목록 조회 화면에서 확인이 된 메시지여도 실제로는 이미 소비되어 삭제할 수 없는 경우가 발생할 수 있다. 따라서 정확한 메시지 삭제를 위해서는 해당 Destination이 소비 일시중지 상태에서 사용할 것을 권장한다.
Queue 또는 Durable subscriber 내의 메시지를 다른 서버나 클러스터로 옮길 수 있는 형태로 내보내는 기능이다.
메시지 내보내기 과정은 다음과 같다.
Destination 화면([그림 6.14])에서에서 내보내려는 메시지를 체크하고 [export] 버튼을 클릭한다.
Message Export 화면에서 'All'을 체크하면 해당 Destination이나 Durable subscriber 내의 모든 메시지를 내보낼 수 있다. [확인] 버튼을 클릭하면 메시지 내보내기가 수행되며 브라우저를 통해 "message.xml"이라는 파일을 다운로드 받는다.
JMS는 메시지가 매우 빠른 속도로 생산되고 소비되기 때문에 목록에는 조회되어도 메시지가 이미 소비되었을 수도 있다. 그러므로 원하는 메시지들을 제대로 내보내기 위해서는 Destination이 소비 일시중지 상태일 때 사용해야 한다.
메시지 내보내기 기능을 수행하면 생성되는 XML 파일을 이용해서 서버 내의 특정 Destination으로 메시지를 가져올 수 있다. 메시지 이동과는 달리 전혀 새로운 메시지로 취급되며, 메시지가 Destination으로 들어오는 순간 새로운 Message ID가 발급된다.
메시지 가져오기 과정은 다음과 같다.
Destination 화면([그림 6.14])에서 대상이 되는 Destination의 [import] 버튼을 클릭한다.
Message Import 화면에서 세부 항목을 설정한 후 [확인] 버튼을 클릭하면 메시지를 가져온다. 이때 'Overwrite'를 체크하면 이전에 있던 메시지의 ID를 그대로 사용하고, 만약 대상이 되는 Destination 내에 같은 ID를 가진 메시지가 이미 존재한다면 그 메시지를 덮어쓴다.
메시지 가져오기에서 'Overwrite' 항목을 체크해서 기존 메시지를 대치할 때 메시지가 이미 클라이언트로 전달되었을 가능성이 있다. 이 경우에는 가져오기는 성공하지만 덮어쓰기는 제대로 수행되지 않는다. 따라서 이 기능을 사용할 때에는 해당 Destination이 소비 일시중지 상태일 때 사용할 것을 권장한다.
서버 내의 Destination별로 생산 및 소비 서비스를 일시중지하거나 재개할 수 있다.
해당 Destination으로 메시지를 생산하는 것을 일시중지하거나 재개하는 기능이다. Destination이 생산 일시중지 상태가 되면 해당 Destination으로 메시지를 생산하는 것이 불가능해진다.
WebAdmin의 [Monitoring] > [JMS] 메뉴를 선택하고 [Destinations] 탭의 [Server]를 선택한다. 해당 서버의 Destination 목록이 조회된다.
각 Destination별로 'Produce suspended' 값을 통해 메시지 생산에 대한 Destination의 현재 상태를 확인할 수 있고 각 버튼을 클릭해서 Destination의 상태를 변경할 수 있다.
설정값 | 설명 |
---|---|
true | 해당 Destination의 생산이 일시중지된 상태이다. |
false | 해당 Destination이 정상적으로 서비스되고 있는 상태이다. |
메시지 생산이 일시중지된 상태('Produce suspended' 값이 true인 상태)의 Destination으로 메시지를 보낼 경우 일정 시간 기다리다가 ExceptionListener를 통해 jeus.jms.common.destination.InvalidDestinationStateException을 통보한다.
해당 Destination에서 메시지 소비를 일시중지하거나 재개하는 기능이다. Destination의 소비가 일시중지 상태가 되면 해당 Destination에서 메시지를 소비하는 것이 불가능해진다.
WebAdmin의 [Monitoring] > [JMS] 메뉴를 선택하고 [Destinations] 탭의 [Server]를 선택한다. 해당 서버의 Destination 목록이 조회된다.
각 Destination별로 'Consume suspended' 값을 통해 메시지 소비에 대한 Destination의 현재 상태를 확인할 수 있고 각 버튼을 클릭해서 Destination의 상태를 변경할 수 있다.
설정값 | 설명 |
---|---|
true | 해당 Destination의 소비가 일시중지된 상태이다. |
false | 해당 Destination이 정상적으로 서비스되고 있는 상태이다. |
메시지 소비가 일시중지된 상태('Consumer suspended' 값이 true인 상태)의 Destination에서 메시지를 소비하려할 경우 해당 Destination에 메시지가 존재하지 않을 때와 동일하게 동작한다.
JEUS MQ를 이용해 메시지를 전달할 때 Persistent Store를 사용하면, 서버의 장애가 발생 했을때에도 높은 신뢰도의 메시지 전달을 보장할 수 있다. 하지만 이것은 JEUS MQ 서버와 메시지 수신자간의 메시지 전달만을 보장하고 있으며, 메시지 송신자가 서버로 전달할 때, 서버 혹은 클라이언트의 장애가 발생했을 때의 메시지 전달은 보장하지 못하고 있다.
이를 보완하기 위해서 JEUS MQ에서는 Persistence Store와 유사한 기능을 하는 JEUS의 Local Persistent Queue를 이용하여 메시지 송신자와 JEUS MQ 서버 간의 신뢰도를 높이는 기능을 제공하고 있다. Local Persistent Queue(이하 LPQ)는 데이터를 로컬의 저장소에 저장한 후, 저장된 데이터는 반드시 주어진 작업대로 처리되는 것을 보장해주는 서비스이다. JEUS MQ에서는 LPQ를 이용하여 전송하고자 하는 메시지를 전송하기 전에 저장해놓고, 메시지가 서버에 전송될 때까지 전송을 시도하여 메시지 송신자에서 서버로의 전송에 대한 신뢰도를 높이고 있다.
LPQ를 이용한 신뢰도 높은 메시지 송신은 다음과 같은 특징이 있다.
서버 상태에 상관없이 메시지 전송에 성공할 때까지 메시지 재전송
클라이언트의 상태 이상으로 전송 실패한 메시지 복구
비동기 메시지 전송
JMS 클라이언트가 메시지를 보낼때, 해당 클라이언트가 Java EE 애플리케이션이고, 메시지를 받는 JMS 서버가 같은 해당 클라이언트가 deploy된 서버라면, 성능 향상을 위해 네트워크를 통하지 않고 메시지를 전달하기 때문에 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 설정 파일의 위치와 설정 방법에 관한 더 자세한 설명은 “6.6.4. LPQ 설정”을 참고한다.
JEUS 전용 API를 통한 활성화
클라이언트 소스에서 JEUS 전용 세션 객체인 JeusSession으로부터 다음 API를 사용하여 LPQ를 활성화시킬 수 있다.
public void startLPQ();
1. JVM 옵션을 통한 경우나 JEUS 전용 API를 통한 경우에도 설정 파일이나 시스템 프로퍼티를 통해 LPQ의 동작을 설정할 수 있다. 설정되지 않은 항목에 대해서는 기본값이 적용된다. LPQ 설정에 관한 더 자세한 설명은 “6.6.4. LPQ 설정”을 참고한다.
2. JEUS 전용 API를 통한 경우가 아니라면 LPQ가 활성화되는 시점이 명시되지 않는데, 이때는 해당 JVM에서 최초의 Connection이 생성될 때 LPQ가 활성화된다. 또한, LPQ가 동작을 멈추는 시점은 마지막 Connection이 close될 때이다. 단, 이때 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 설정을 하더라도 무시된다.
메시지 전송에 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);
LPQ는 실패한 전송에 대한 처리, 연결이 끊어졌을 때의 동작, 저장소의 위치 또는 크기에 대한 설정들이 필요하다.
다음은 LPQ 설정 항목에 대한 설명이다.
공통 항목
전달 관련 항목
재연결 관련 항목
저장소 관련 항목
다음은 LPQ 설정 방법에 대한 설명이다.
설정 방법 간의 우선순위는 런타임 프로퍼티 설정 > 설정 파일 > JVM 옵션 순이다.
설정 파일
LPQ 설정 파일이 지정된 위치에 존재한다면 LPQ가 활성화될 때 그 파일을 읽어 활성화되는 LPQ에 해당 설정을 적용시킨다. 지정된 위치는 APP_HOME/WEB-INF/, APP_HOME/META-INF/, APP_HOME/으로 상기한 순서대로 설정 파일을 찾는다. 설정 파일의 세부 경로의 기본값은 '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>);