본문으로 건너뛰기

16.8 EJB 애플리케이션 클러스터

EJB 애플리케이션에서도 클러스터링에서 필요한 로드 밸런싱, 세션 복제, 장애 복구기능을 모두 제공한다. 다음은 EJB 애플리케이션을 클러스터링 구성했을 경우, 클라이언트와 호출을 나타낸 그림이다.

그림 9. JBoss EAP 6의 EJB 클러스터링

다음의 표. 10은 Stateful세션 빈(SFSB)과 Stateless 세션 빈(SLSB)의 클러스터링 기능을 정리한 것이다.

Stateless 세션 빈은 상태를 가지지 않기 때문에 복제할 세션이 없다. Stateful 세션 빈의 경우, 로드 밸런싱 기능과 세션을 복제하여 클러스터링을 구성한다.

세션 빈 종류로드밸런싱세션 복제장애 복구
Stateful세션 빈OOO
Stateless 세션 빈OXO

표 11. Stateful세션 빈과 Stateless 세션 빈의 클러스터링 기능 비교

  • 로드밸런싱 EJB 애플리케이션에 대한 로드 밸런싱은 EJB 클라이언트의 라이브러리에서 제공한다.

  • 세션 복제 ‘EJB 세션 복제’는 웹 세션 복제와 마찬가지로 SFSB의 상태를 다른 서버에 복사해 놓는 기능이다. 상태를 복제해 놓았기 때문에, 특정 서버 노드가 정지했을 경우에도 상태를 잃지 않고, SFSB을 계속 처리할 수 있다.

  • 장애 복구 EJB 애플리케이션의 장애 복구는 EJB 애플리케이션 실행 중 서버에 장애가 발생했을 때, 다른 서버 노드가 처리를 계속하는 기능이다. 이 기능은 EJB 클라이언트와 세션 복제 기능(SFSB)으로 제공한다. EJB 클라이언트는 서버 노드의 장애를 감지하면, 접속하고 있는 클러스터내의 다른 서버 노드에서 수행 중이던 처리를 다시 실행한다.

EJB 클러스터링 테스트

다음에서는 실제 EJB 애플리케이션의 클러스터 환경 구축과 리모트 호출 방법을 설명한다.

EJB 애플리케이션 클러스터 환경 구축

EJB 애플리케이션 클러스터링을 구성하려면 웹 클러스터링과 마찬가지로 ha, full-ha 프로파일을 사용하면 된다. 스탠드얼론 서버의 경우엔 standalone-ha.xml, standalone-full-ha.xml을 사용한다.

웹 애플리케이션과 같이 ha 프로파일에 미리 EJB 세션 복제 설정이 되어 있기 때문에, 같은 설정의 JBoss EAP 6 인스턴스를 여러 개 실행하면, 자동으로 감지해 클러스터를 구성한다. 로드 밸런싱만을 사용하고 싶어도 서버 측에 클러스터를 구성해야 한다. EJB 클라이언트에서 원격의 EJB를 로드밸런싱할 때, 클러스터에 있는 서버리스트를 받아서 호출하기 때문이다.

Stateful 세션 빈 개발

Stateful 세션 빈 구현할 때 세션을 복제하고 싶은 클래스에 @Clustered 어노테이션(org.jboss.ejb3.annotation.Clustered)을 기술한다. 다음은 구현 예제이다. 이제 EJB 개발이 정말 쉬워졌다.

package com.opennaru.ejb;

import javax.ejb.Remote;
import javax.ejb.Stateful;
import org.jboss.ejb3.annotation.Clustered;

@Stateful
@Clustered
@Remote(IHello.class)
public class Hello implements IHello {
private int counter = 0;

public String doSomething() {
return ("Hello EJB3 called : " + (++counter) );
}
}

@Clustered 어노테이션을 사용하려면 메이븐 pom.xml파일에 jboss-ejb3-ext-api을 추가하여 컴파일 해야 한다.

<dependency>
<groupId>org.jboss.ejb3</groupId>
<artifactId>jboss-ejb3-ext-api</artifactId>
<version>2.1.0</version>
<scope>provided</scope>
</dependency>

@Clustered 어노테이션을 기술한 클래스를 JBoss에 배포하면, JBoss는 자동으로 세션 복제 대상 클래스를 찾아 세션을 다른 서버 노드에 복제한다.

다음은 server1를 시작 후 server2를 기동시켰을 경우의 로그이다.

22:09:27,250 INFO [stdout] (ServerService Thread Pool -- 61) -------------------------------------------------------------------
22:09:27,250 INFO [stdout] (ServerService Thread Pool -- 61) GMS: address=server1/ejb, cluster=ejb, physical address=192.168.0.28:55200
22:09:27,250 INFO [stdout] (ServerService Thread Pool -- 61) -------------------------------------------------------------------
22:09:29,253 INFO [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (ServerService Thread Pool -- 61) ISPN000094: Received new cluster view: [server1/ejb|0] [server1/ejb]
22:09:29,331 INFO [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (ServerService Thread Pool -- 61) ISPN000079: Cache local address is server1/ejb, physical addresses are [192.168.0.28:55200]

… 중략 …

22:09:29,481 INFO [org.jboss.web] (ServerService Thread Pool -- 61) JBAS018210: Register web context: /helloejb
22:09:29,536 INFO [org.jboss.as.server] (HttpManagementService-threads - 1) JBAS018559: Deployed "helloejb.war" (runtime-name : "helloejb.war")
22:09:47,856 INFO [org.jboss.as.clustering] (Incoming-3,shared=udp) JBAS010225: *New cluster view for partition ejb (id: 1, delta: 1, merge: false) : [server1/ejb, server2/ejb]*
22:09:47,860 INFO [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (Incoming-3,shared=udp) ISPN000094: *Received new cluster view: [server1/ejb|1] [server1/ejb, server2/ejb]*

리모트 호출 처리의 구현

InitialContext를 초기화해 lookup한 후, 리모트 EJB를 호출한다. 호출하는 클라이언트 코드는 다음과 같다.

package com.opennaru.ejb;

import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;

public class HelloClient {
public static void main(String[] args) throws Exception {

Properties p = new Properties();

p.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

InitialContext ctx = new InitialContext(p);
IHello ejb = (IHello) ctx.lookup("ejb:/helloejb/Hello!" + IHello.class.getName() + "?stateful");

for (int i = 0; i < 10; i++) {
System.out.println( ejb.doSomething() );
}
}
}

InitialContext의 초기화에 사용할 프로퍼티 파일에 클러스터 환경용 설정을 추가하여야 한다. 다음은 jboss-ejb-client.properties의 설정 예이다.

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=server1,server2
remote.connection.server1.host=192.168.0.101
remote.connection.server1.port=4447
remote.connection.server1.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.server1.username=admin
remote.connection.server1.password=opennaru!234
remote.connection.server2.host=192.168.0.101
remote.connection.server2.port=4547
remote.connection.server2.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.server2.username=admin
remote.connection.server2.password= opennaru!234

원격의 서버리스트를 remote.connections에서 server1, server2로 정의하였고, 해당 서버에 대한 정보를 프로퍼티 파일 안에서 server1, server2에 대한 IP, 포트를 설정하였다.

JBoss EAP 6에서 EJB 애플리케이션 배포를 위한 클러스터링 환경 구축, 구현 및 리모트 호출 방법에 대해 살펴보았다.