내용 목차
본 장에서는 Stateless Session Bean과 Stateful Session Bean에 대해서 자세히 설명한다.
Stateless Session Bean은 사실상 “제4장 EJB의 공통 특성”에서 설명한 내용 외에는 특별한 것이 없다. 따라서 본 장에서는 주로 Stateful Session Bean들에 대해 설명한다.
본 절에서는 Session Bean의 TTP(Thread Ticket Pool)에 대해 설명한다.
Stateless Session Bean은 클라이언트의 요청에 관련된 상태 정보를 가지고 있지 않기 때문에 모든 클라이언트가 connection을 공유해서 Connection Pool은 설정할 필요가 없다. 그러나 상태 정보를 가지고 있지 않은 이유로 Bean Instance를 재활용할 수 있기 때문에 Bean Pool을 설정할 수 있다.
다음은 Stateless Session Bean의 TTP과 Bean Pool의 관계를 나타낸 그림이다.
create 시점에 클라이언트와 연결을 맺은 connection으로 요청을 하면 TTP에서 TT(Thread Ticket)를 발급받는다. TT를 발급받지 못하면 TT를 발급받을 때까지 기다린다. 기다리는 시간이 10분을 초과하면 RemoteException이 발생하여 요청을 수행하지 못한다. (“제4장 EJB의 공통 특성” 참고)
TT를 발급받은 클라이언트의 요청을 수행하기 위해 실제 Bean instance를 Bean Pool로부터 할당받아 connection과 연결을 맺는다.
Stateless Session Bean Instance가 처리를 끝냈을 때 TT는 TTP로 반환되고 Bean Instance는 Bean Pool로 반환되어 다음 클라이언트 요청을 기다린다. 즉, 매 요청마다 TT와 Bean Instance를 새로 할당받고 요청이 끝나면 반환된다.
Bean Pool 개수의 의미가 TTP 개수의 의미와 다른 점은 동시 수행될 수 있는 로컬 클라이언트와 리모트 클라인언트의 요청의 개수와 관련된다는 점이다. 즉, Remote call은 TTP에서 TT를 할당받은 후 Bean Pool에서 Instance를 할당받을 수 있고, Local call은 클라이언트 스레드에서 바로 수행되므로 TT를 발급받을 필요가 없고 Bean Pool로부터 Instance만 할당받는다.
따라서 jeus-ejb-dd.xml의 <thread-max>의 값을 적게 설정하면 설정값 이상의 Remote call은 받을 수 없고 Bean Pool의 최댓값은 무한대이기 때문에 Local call은 처리할 수 있다.
EJB 2.1 이후부터 Stateless Session Bean은 웹 서비스 형태로 Export될 수 있다.
이에 대한 자세한 정보는 "JEUS Web Service 안내서"를 참고한다.
본 절에서는 다음의 Stateful Session Bean의 추가적인 설정들의 개념에 대해 설명한다.
Object Management 설정 : Bean Instance Pool과 Connection Pool
Bean Instance Pooling 옵션
Session Manager를 통한 상태 유지 메커니즘
Stateful Session Bean은 클라이언트의 요청에 관련된 상태 정보를 지속적으로 유지하고 있어야 하기 때문에 Stateless Session Bean과는 달리 Connection Pool을 설정하고 활용해야 한다. 이는 Entity Bean에도 동일하게 적용된다. 자세한 내용은 “제8장 Entity Bean”을 참고한다.
다음은 Stateful Session Bean의 Connection Pool과 TTP, Bean Pool의 관계를 나타낸 그림이다.
클라이언트가 Stateful Session Bean을 생성하면 새로운 Bean Instance(SF Instance)가 만들어지고 Connection Pool에서 connection을 꺼내 2개가 연결된다. Bean Instance와 연결된 connection을 클라이언트에게 넘겨주면 이 connection은 현 클라이언트에게 할당되고 다른 클라이언트와 공유하지 않는다. 따라서 클라이언트가 제거하지 않는 한 다시 Connection Pool로 반환되지 않는다. Connection Pool로 반환될 때에는 연결되었던 Bean Instance와의 연결을 끊는다.
해당 connection으로 요청을 하면 TTP에서 TT를 받는다. TT를 받은 요청만 처리한다. Stateless Session Bean과 달리 매 요청마다 새로운 Bean Instance가 Bean Pool로부터 할당되는 것이 아니라 해당 클라이언트를 위한 Bean Instance가 고정되어 있다.
앞에서 설명했듯이 이 Bean Instance는 클라이언트가 Bean을 제거했을 때 connection이 Connection Pool로 반환되면서 connection과의 연결을 잃으면서 삭제된다. 기본적으로 Stateful Session Bean은 상태가 있기 때문에 Bean Instance를 재활용하는 Bean Pool을 사용하지 않는다.
EJB 표준에 따르면, 실제 Stateful Session Bean의 Instance는 다른 클라이언트 Session에서 재사용할 수 없다. 그러나 Bean이 제거될 때 초기화가 제대로 이루어진다면 Bean Instance를 재사용할 수도 있다. JEUS는 Bean Instance를 매번 생성하지 않는 점에서 성능 개선과 자원 낭비를 줄이기 위해 이를 재사용하는 방법을 제공한다.
Bean Pool을 사용하면 Bean이 제거될 때 해당 Bean Instance가 Bean Pool로 반환된다. Bean의 제거는 클라이언트가 명시적으로 remove를 부르거나 오랫동안 요청이 없어 타임아웃이 된 경우에 발생한다. 이때 PRE DESTROY callback이 불리게 되는데 여기서 Bean의 초기화를 잘 구현한 경우에만 사용하도록 권장한다.
Stateful Session Bean을 Pooling Bean으로 전환하려면 간단히 jeus-ejb-dd.xml의 <pooling-bean> 값을 true로 설정한다.
[예 7.1] Bean Pool 설정 : <<jeus-ejb-dd.xml>>
<jeus-ejb-dd> . . . <beanlist> <jeus-bean> <ejb-name>teller</ejb-name> <export-name>TELLEREJB</export-name> <local-export-name>LOCALTELLEREJB</local-export-name> <export-port>7654</export-port> <export-iiop>true</export-iiop> <object-management> <pooling-bean>true</pooling-bean> <bean-pool> <pool-min>10</pool-min> <pool-max>200</pool-max> <resizing-period>1800000</resizing-period> </bean-pool> . . . </object-management> . . . </jeus-bean> . . . </beanlist> . . . </jeus-ejb-dd>
이름에서 암시하듯이 Stateful Session Bean은 상태를 지니고 다닌다. 이 상태는 클라이언트 세션 동안 반드시 유지되어야 한다. 즉, 같은 클라이언트로부터 오는 모든 다른 요청에도 상태는 지속되어야 한다. 이것이 Stateful Session Bean의 기본 특성이다.
일반적으로 런타임할 때의 상태는 Instance 변수로 저장된다. 그러나 위에서 설명한 것과 마찬가지로 Stateful Session Bean이 passivate 상태로 진입하면 시스템 자원을 보존하기 위해 운영환경에서 이 Instance 변수들을 제거해야 한다. 그러나 Bean이 다시 재활성화되면 상태를 복구하기 위해서 어딘가에서 데이터를 가져와야 한다. 즉, 2차 저장소가 필요하다.
JEUS에 포함된 분산식 Session Manager를 2차 저장소로 사용한다. 기본적으로는 passivate될 때 클러스터링으로 구성된 Stateful Session Bean의 경우는 Failover를 위해 트랜잭션의 commit이 성공적으로 수행될 때로 Bean의 정보가 Session Manager로 전달된다. Session Manager는 DAS에서 설정된다.
설정에 대한 자세한 내용은 “6.3.3. Stateful Session Bean의 클러스터링 설정”을 참고한다.
본 절에서는 Stateless Session Bean과 Stateful Session Bean의 공통 설정 항목에 대해서 설명한다. 이 모든 항목들은 JEUS EJB 모듈 DD의 <jeus-bean> 태그 아래에 설정된다.
Stateless Session Bean은 상태가 없어서 하나의 connection만 사용해도 무방하기 때문에 Bean Pool만 사용할 수 있고, Stateful Session Bean은 상태가 있기 때문에 Connection Pool과 Bean Pool을 모두 사용할 수 있다. 따라서 다음과 같이 제공되는 설정을 통해 Pool을 이용하면 매번 Instance를 생성하는 부하를 줄일 수 있다.
다음은 Object Management 관련 설정한 XML 예제이다.
[예 7.2] Object Management 설정 : <<jeus-ejb-dd.xml>>
<jeus-ejb-dd> . . . <beanlist> <jeus-bean> . . . <object-management> <bean-pool> <pool-min>10</pool-min> <pool-max>200</pool-max> </bean-pool> <connect-pool> <pool-min>10</pool-min> <pool-max>200</pool-max> </connect-pool> <passivation-timeout>10000</passivation-timeout> <disconnect-timeout>1800000</disconnect-timeout> </object-management> <jeus-bean> . . . <beanlist> . . . <jeus-ejb-dd>
다음은 <object-management>의 하위 설정 태그에 대한 설명이다.
<bean-pool>
EJB Bean Instance Pool의 작동 방식을 결정한다.
하위 태그들은 다음과 같다.
태그 | 설명 |
---|---|
<pool-min> | Pool을 초기화할 때 생성해두는 초기 Bean Instance 개수이다. (기본값: 0) |
<pool-max> | Instance의 사용이 완료된 후 Pool에 저장 가능한 최대 Bean Instance 개수이다. (기본값: 100) |
<resizing-period> | Pool의 크기를 재조정하는 시간으로 "resizing"은 사용되지 않는 Bean Instance들이 Pool의 최솟값까지 제거됨을 의미한다. (기본값: 5분, 단위: ms) |
<connect-pool>
클라이언트와 Bean Instance를 연결하는 connection을 몇 개까지 유지할지를 설정한다(해당 옵션은 JEUS 6 Fix#8부터 Session Bean에서는 사용하지 않는다).
하위 태그들은 다음과 같다.
태그 | 설명 |
---|---|
<pool-min> | Pool을 초기화할 때 생성해두는 초기 connection 개수이다. (기본값: 0) |
<pool-max> | connection 사용이 완료된 후 Pool에 저장 가능한 최대 connection 개수이다. (기본값: 100) |
<resizing-period> | Pool의 크기를 재조정하는 시간으로 "resizing"은 사용되지 않는 Bean Instance들이 Pool의 최솟값까지 제거됨을 의미한다. (기본값: 5분, 단위: ms) |
<passivation-timeout>
지정된 시간 동안 클라이언트의 요청을 받지 않은 Stateful Session Bean을 passivate할 때 사용된다. 그러므로 여기에 설정된 시간을 초과하는 동안 클라이언트의 요청이 없으면 그 Bean은 passivation의 대상이 된다.
어떤 Bean이 passivation 대상이 되는지를 검사하는 주기는 EJB 엔진에 설정한 resolution을 따른다. Passivation이 실행되면 메모리에서 해당하는 Bean Instance가 제거되고 Instance의 상태는 파일에 저장된다. 내부적으로 분산 세션 서버를 사용한다.
이 설정은 여러 곳에서 설정이 가능하고 우선순위는 다음과 같다.
특정 Session Bean에만 적용 : jeus-ejb-dd.xml의 <passivation-timeout>
모든 Stateful Session Bean에 적용 : 시스템 프로퍼티 jeus.ejb.stateful.passivate
모든 EJB Bean에(Entity Bean과 Session Bean 모두) 적용 : 시스템 프로퍼티 jeus.ejb.all.passivate
모든 EJB Bean에(Entity Bean과 Session Bean 모두) 적용 : DAS의 <node>/<session-router-config>/<session-router>/<file-db>/<passivation-to>
위의 모든 설정이 없으면 기본값으로 설정된다. (기본값: 300000(5분), 단위: ms)
<disconnect-timeout>
지정된 시간 동안 클라이언트의 요청을 받지 못하면 클라이언트와 Stateful Session Bean Instance 사이를 연결하던 connection을 끊을 때 사용된다. 그렇게 되면 connection은 각각의 클라이언트 및 Instance와 맺고 있던 연결을 끊고 Connection Pool로 반환된다.
따라서 클라이언트는 이 connection으로 더 이상 요청을 할 수 없고, 사용 중이던 Bean Instance는 삭제되거나 Bean Pool을 사용 중이면 Bean Pool로 반환된다.
이 설정은 여러 곳에서 설정 가능하고 우선순위는 다음과 같다.
특정 Session Bean에만 적용(순서대로 우선순위)
ejb-jar.xml의 <stateful-timeout>
@StatefulTimeout
(Deprecated) jeus-ejb-dd.xml의 <disconnect-timeout>
모든 Stateful Session Bean에 적용 : 시스템 프로퍼티 jeus.ejb.stateful.disconnect
모든 EJB Bean에(Entity Bean과 Session Bean 모두) 적용 : 시스템 프로퍼티 jeus.ejb.all.disconnect
위의 모든 설정이 없으면 시스템 프로퍼티 jeus.ejb.all.disconnect의 기본값으로 설정된다.
(기본값: 3600000(1시간), 단위: ms)
<passivation-timeout>과 <disconnect-timeout>에 사용되는 시간은 Bean Instance에 액세스했던 마지막 시점부터 측정된다. 그러므로 <disconnect-timeout>을 <passivation-timeout>보다 길게 설정해야 한다. 또한 <passivation-timeout>은 EJB 엔진에 설정되는 resolution보다는 커야한다.
타임아웃 값을 길게 설정하면 오랜 시간(대략 십여 분 이상 또는 타임아웃이 중지된 경우) 동안 메모리 내의 많은 Instance가 활성화된 상태로 머물러 있다. 그러므로 시스템 자원 낭비를 초래한다. 너무 짧은 타임아웃 값은(수 초) passivation, activation 등의 작업이 너무 자주 발생하므로 성능을 저하시킬 수 있고 disconnect 작업으로 인해 세션 유실 가능성이 있다.