티스토리 뷰

728x170

포스팅은 J2EE Spec 중 JMS QUEUE 가이드니다.


Java Message Service(JMS)에 대해서 알아보고 JEUS에서 간단한 예제를 실행시켜보는 것을 목적으로 합니다.



먼저 JMS 개요입니다.

JMS는 SUN에서 만들어진 엔터프라이즈 메시징을 위한 API로서 메시징 시스템 자체만이 아니라 메시징 시스템과 통신하는 메시지 클라이언트에서 필요한 클래스와 인터페이스에 대한 추상화도 포함합니다.
JMS는 사용자가 생성한 Message를 가상채널로 전달하고 이 가상채널로부터 필요한 Message를 얻어올 수 있다. 또한 Message는 등록된 사용자로 전달이 보장됩니다.


다음으로 JMS 특징에 대해 살펴보겠습니다.

Asynchronous로써 메시지가 비동기식으로 전달됩니다.

수신자가 수신이 가능하지 못 할 경우에 메시지 서버가 영속장치에 메시지를 저장하고 수신자의 수신이 가능해지면 모든 메시지를 받게하는 보장된 전달을 수행합니다.

Sender와 Receiver간의 TCP 패킷을 정의하여 통신하는 Interface-centric 방식의 통신이 아닌 Data-centric(데이터 중심의)방식으로 메시지를 주고 받는데 Sender와 Receiver간의 약속이 필요하지 않습니다.

메시지는 오직 한번만 전달됩니다. Destination에 전달된 메시지는 전달받으려는 클라이언트에게 전달된 후에는 다시 전달되지 않습니다.


그럼 이제 JMS Message Model에 대해 살펴보겠습니다.

먼저 Point-to-Point 모델입니다.

발신자가 큐를 통해 하나의 수신자에게 메시지를 전달하는 1:1방식입니다.

여러명의 수신자가 있을 수 있으나 메시지 하나는 한 수신자에게만 허락됩니다
메시지에 순서가 있다. 메시지가 메시지 서버에 의해 위치한 순서대로 큐가 메시지를 수신자에게 전달합니다.


다음으로 가장 많이 사용하는 Publish/Subscribe 모델입니다.

발행자(생산자)가 토픽을 통해 많은 구독자(소비자)들에게 메시지를 전달하는 1:다 방식입니다.
구독자가 새로운 메시지를 받으려고 토픽에 요청하지 않아도 자동적으로 전달되는 푸시기반모델입니다.
발행자가 메시지를 받는 구독자에게 의존하지 않습니다.
구독자가 중간에 연결을 끊은 경우 나중에 접속하면 끊어진 동안 발행한 메시지를 모아서 받을 수 있습니다.


다음으로 메시지 전달방법에 대해 알아보겠습니다.

메시지 전달 방법에 영속적(persistent)인 방법과 비영속적(nonpersistent)인 방법이 있으며 두 방식 모두 같은 소비자에게 같은 메시지를 한 번보다 더 많이 전달하면 안됩니다. (다만 소비자가 메시지를 받고 확인응답을 제공자에게 전달하기 전에 장애가 나면 제공자는 메시지가 전달되지 않은 것으로 파악하고 재전송을 시도합니다.)

먼저 Persistent 방식입니다.

JMS 서비스 제공자가 잘못 될 경우 메시지가 손실되지 않도록 무조건 한번 방식 (onsc-and-only-once)으로 전달됩니다. 이는 무조건 한번은 발행해야 하며 두번 이상은 안됨을 말합니다.
서버가 복구되면 다시 전달됩니다.
저장 후 전달(store-and-forward) 메커니즘을 이용하게 됩니다.


다음으로 Nonpersistent 방식입니다.

JMS 서비스 제공자가 잘못될 경우 메시지가 손실될 수도 있는 최대 한번 방식 (at-most-once)으로 전달합니다. 한 번도 안 일어날 수 있지만 있다면 단 한번이어야 함을 말합니다.


마지막으로 Durable Subscriber입니다.

Topic방식으로 메시지를 전달 시 Subscriber가 inactive 상태이면 해당 Subscriber에 대해 메시지를 잃어버리게 되는데 DurableSubscriber로 등록되면 inactive상태에서도 메시지를 가져갈 때까지 메세지를 저장해 둡니다. 이는 Topic방식에서만 제공됩니다.


마지막으로 위에서 살펴본 내용을 토대로 JMS를 개발해 보도록 하겠습니다.
먼저 어플리케이션 구성요소들을 살펴보겠습니다.

ConnectionFactory는 JMS 서비스에 연결하기 위한 Connection을 생성할 때 사용하는 객체입니다.
TopicConnectionFactory, QueueConnectionFactory의 기본형입니다.
클라이언트는 프로그램 시작 부분에 JNDI를 통해 ConnectionFactory를 검색합니다.


Destination는 생성된 메시지가 저장되는 저장소, 그리고 메시지가 소비되는 곳으로 사용되는 가상채널입니다.
먼저 ConnectionFactory를 NamingServer에서 검색하고, 다음 Destination을 검색입니다.


Session은 Message를 생성하고 소비하는 단일 쓰레드 단위입니다.

Application에서 Message를 보내고 받기 위한 최소한의 단위를 트랜잭션이라하는데 Session은 이런 트랜잭션 기능을 제공합니다.


Message는 Application들이 교환하는 정보들을 담고 있습니다.
메시지 타입에는 Message, TextMessage, ObjectMessage, StreamMessage, BytesMessage, MapMessage 6가지가 있습니다.
Header, Property, Body의 세 부분으로 나뉩니다.


MessageConsumer는 Destination에 전달된 Message를 전달받는 역할입니다.
MessageListener : 메시지를 비동기적으로 전달받을 수 있도록 해줍니다.
동기적으로 메시지를 전달받을 때는 receive(), receive(long timeout), receiveNoWait() 중 하나를 선택하여 호출하여야 합니다.


MessageProducer는 Destination에 Message를 전달하는 역할입니다.

setDeliveryMode(), close(), setPriority(), setTimeToLive(long timeToLive) 등 클라이언트에서 사용하는 몇 가지 일반목적의 메소드를 갖습니다.


다음으로 JMS 어플리케이션의 구조에 대해 알아보겠습니다.

먼저 ConnectionFactory를 lookup합니다
이후 Connection과 Session을 만듭니다
메시지를 전달할 Destination을 lookup합니다
Message Producer 또는 Message Consumer를 만들거나 MessageListener를 등록합니다
비즈니스 로직을 담는 어플리케이션 로직을 수행합니다.
마지막으로 Connection을 닫습니다


다음으로 JMS 메시지 구조에 대해 알아보겠습니다.
JMS 메시지는 어플리케이션 데이터 전송과 이벤트가 발생했음을 알려주는 기능을 제공합니다. 메시지는 수신측에서 어떻게 해야하는지 지정하지 않으며 발신측이 응답을 기다려야 할 필요도 없습니다. 발신측과 수신측을 이렇게 분리함으로써 요청-응답의 개념보다 훨씬 동적이며 융통성있게 됩니다. 메시지는 Header, Property, Body 3부분으로 구성됩니다.

먼저 Header 부분입니다.

누가 혹은 어떤 메시지를 생성했는지, 언제 했는지, 얼마 동안 유효한지 등을 기술하고 있는 메타데이터를 제공합니다. 메시지의 목적지가 어디인지 기술하는 경로정보, 어떻게 확인할 수 있는지 등의 정보를 내포하고 있습니다.

주요 요소만 살펴보자면 다음과 같습니다.

JMSDestination는 메시지가 배달될 Queue나 Topic의 Destination을 가리킵니다.

JMSExpiration는 Message객체의 만료 값을 나타냅니다. 이때 기간이 만료된 후에는 메시지가 소비자에게 전달되지 않습니다.

JMSPriority는 메시지에 대한 우선등급을 나타냅니다.

JMSReplyTo는 메시지를 받은 Application이 응답 메시지를 보내야 하는 Destination을 담고 있습니다. 따라서 JMSCorrelationID와 함께 request/reply 형태의 Application에서 사용할 수 있습니다.


다음으로 Property 부분입니다.

메시지에 할당할 수 있는 부가적인 헤더와 같은 역할을 합니다.

Property는 Java의 표준인 이름/값(name/value) 쌍으로 지정됩니다.
Property의 이름은 javax.jms.Message javadoc에 정의되어 있는 Message Selectors 형식을 따라야 합니다. 그리고 값은 Boolean, Byte, Double, Float, Integer, Long, Short, String 타입의 객체만 지정 가능합니다.

메시지가 보내지면 속성은 읽기전용으로 바뀝니다. 소비자가 속성을 변경하려하면 javax.jms.MessageNotWriteableException예외가 발생합니다.
clearProperties() 메소드를 이용하여 바꿀 수 있으나 이 메소드는 메시지의 모든 속성을 제거하여 새 속성을 추가하는 것입니다.


마지막으로 Body 부분입니다.

Message, TextMessage, ObjectMessage, StreamMessage, BytesMessage, MapMessage 6가지 바디타입을 제공합니다.

먼저 Message는 본문이 없는 메시지를 생성할 때 사용하는 메시지타입입니다. JMS 헤더들과 속성만을 가지며 이벤트의 통지에 사용될 수 있습니다.

다음으로 TextMessage는 java.lang.String 형의 본문을 갖는 메시지타입입니다. 간단한 텍스트 메시지나 XML같은 복잡한 문자형 데이터의 교환에 유용합니다.
ObjectMessage는 직렬화가 가능한 자바 객체를 본문으로 갖는 메시지타입입니다.
StreamMessage는 기본 데이터형(int, char 등)의 스트림을 본문으로 갖는 메시지 타입입니다.
BytesMessage 기본 데이터형 행렬을 본문으로 갖는 메시지 타입입니다. 다른 Message 타입에서 지원하지 않는 어플리케이션 자체 포맷의 데이터를 교환할 때 유용합니다.
마지막으로 MapMessage는 이름-값의 쌍을 본문으로 갖는 메시지 타입입니다. 이름은 반드시 String 객체이여야 하고 값은 기본 데이터형이 될 수 있습니다.


마지막으로 JEUS의 JMS에 대해 소개 하고 본 포스팅을 마치도록 하겠습니다.

Fail-over를 지원하여 메시지 전송에 대한 신뢰성을 높입니다.
다른 JMS Server 그리고 다른 운영체제에서도 메시지 처리가 가능합니다.
사용자 어플리케이션의 세팅에 따라서 또는 자동적인 트랜잭션의 요구에 참여하므로써 global transaction 이나 local transaction 에 참여 합니다.
사용자 어플리케이션과 서버 destination 사이에 최적화된 메시지를 보낼 수 있도록 합니다.
사용자들에게 실행중인 client API 뿐만 아니라 jmsadmin 을 통해서 관리할 수 있도록 합니


JMS는단방향 통신이 중요시 되는 군부대 작전 시 또는 메신저, 이메일 등에서 매우 유용하게 사용되는 기능입니다. 새로운 기술을 도입하고자 하는 pro들께서 한번쯤 고민해 볼수 있는 기능이라 여겨집니다.

맙습니다.

그리드형
댓글
댓글쓰기 폼