JBoss 5.1.0 GA 세션 클러스터링
WEB/JBossAS / 2010. 5. 23. 00:33
JBoss 에서 고가용성(High Availability) 환경을 구성하기 위해서는 세션 클러스터링이 필요합니다.
테스트에 사용된 환경은 다음과 같습니다.
System: VMWare
OS: CentOS 5.5 x86-64
HTTP Server: Apache HTTP Server 2.2.3
WAS: JBoss 5.1.0 GA
[그림 1] 서버 구성
위의 [그림 1] 에서 보는 것 처럼 하나의 시스템에 하나의 Apache HTTP Server 와 두 개의 JBoss Web Application Server 로 구성할 것 입니다.
http://www.jboss.org/jbossas/downloads.html 에서 5.1.0 GA 를 다운 받습니다.
압축을 풀고 적당한 위치 (/usr/local/jboss5) 에 올립니다.
default configuration 에는 클러스터링 설정이 되어있지 않아 all configuration 을 사용해야 합니다.
[그림 1] 과 같이 node1, node2 두 개의 노드로 구성하기 위해서 all configuration 을 복사합니다.
# cd /usr/local/jboss5/server
# cp -r all node1
# cp -r all node2
# cp -r all node1
# cp -r all node2
하나의 시스템의 두 개의 JBoss 가 올라가기 때문에 실행 시 옵션을 설정해주어야 합니다.
첫번째 인스턴스(node1) 실행
# cd /usr/local/jboss5/bin
# ./run.sh -c node1 -g VickiPartition -u 239.255.100.100 -b 192.168.0.11 -Djboss.messaging.ServerPeerID=1 -Djboss.service.binding.set=ports-default
# ./run.sh -c node1 -g VickiPartition -u 239.255.100.100 -b 192.168.0.11 -Djboss.messaging.ServerPeerID=1 -Djboss.service.binding.set=ports-default
두번째 인스턴스(node2) 실행
# cd /usr/local/jboss5/bin
# ./run.sh -c node2 -g VickiPartition -u 239.255.100.100 -b 192.168.0.11 -Djboss.messaging.ServerPeerID=2 -Djboss.service.binding.set=ports-01
# ./run.sh -c node2 -g VickiPartition -u 239.255.100.100 -b 192.168.0.11 -Djboss.messaging.ServerPeerID=2 -Djboss.service.binding.set=ports-01
Jboss options | |
-c | configuration 을 설정하는 것 입니다. all 을 통해 복사한 node1, node2 를 각 인스턴스별로 설정합니다. |
-g | 클러스터 이름을 설정합니다. (그냥 자기가 좋아하는 이름을 지정하면 될 것 같습니다.) |
-u | 내부 클러스터 통신을 위한 멀티캐스트 주소를 설정합니다. |
-b | 소켓에 바운딩될 아이피 주소를 설정합니다. |
System properties | |
jboss.messaging.ServerPeerID | 각 노드마다 지정되는 유니크한 정수 값 입니다. 1부터 순차적으로 증가하면 될 것 같습니다. |
jboss.service.binding.set | ServiceBindingManager 를 통해 포트 설정을 위한 프로퍼티입니다. 시스템별 첫번째 인스턴스에는 ports-default 로 설정하고 그 다음 인스턴스부터는 ports-01, ports-02 ... 과 같이 설정을 합니다. 기본적으로 JBoss 의 포트가 8080 이고 AJP 1.3 포트가 8009 라면 ports-default 는 8080, 8009 로 바인딩 되고, ports-01 은 8180, 8109 로 바인딩 됩니다. |
나중에 나오겠지만 mod_jk 설정을 위해 미리 jvmRoute 를 설정합니다.
<JBOSS_HOME>/server/"node1|node2"/deploy/jbossweb.sar/server.xml
<Engine name="jboss.web" defaultHost="localhost" jvmRoute="node1">
... ...
</Engine>
각 인스턴스 별로 <Engine> element 의 attribute 로 jvmRoute 를 설정합니다.... ...
</Engine>
웹 어플리케이션을 어떤 방식으로 배포하냐에 따라서 설정이 달라지게 됩니다.
두 인스턴스의 deploy 경로에 각각 배포를 하는 방식이 있고, 한 곳에 배포하여 공유하여 사용하는 방식이 있습니다.
한 곳의 배포하는 방식 중에 한가지는 farm 을 이용하는 것 입니다.
<JBOSS_HOME>/server/node1/farm 에 배포를 하게 되면 각 인스턴스들이 공유하여 사용할 수 있습니다.
(해보지는 않았습니다... 어디선가 본 자료입니다.)
다른 방법으로는 같은 배포 경로를 각 인스턴스에 설정을 하는 것 입니다.
<JBOSS_HOME>/server/"node1|node2"/conf/bootstrap/profile.xml
<deployment>
...
<!--
The profile configuration
This contains required properties:
The uri to jboss-service.xml.
The uri to the deployers folder.
A list of uris to deploy folders. -->
<bean class="org.jboss.system.server.profileservice.repository.StaticProfileFactory" name="BootstrapProfileFactory">
<property name="bindingsURI">${jboss.server.home.url}conf/bindingservice.beans</property>
<property name="bootstrapURI">${jboss.server.home.url}conf/jboss-service.xml</property>
<property name="deployersURI">${jboss.server.home.url}deployers</property>
<property name="applicationURIs">
<list elementclass="java.net.URI">
<value>${jboss.server.home.url}deploy</value>
<value>file:/home/webapps</value>
</list>
</property>
<property name="attachmentStoreRoot">${jboss.server.data.dir}/attachments</property>
<property name="profileFactory"><inject bean="ProfileFactory"></inject></property>
</bean>
...
</deployment>
저의 경우에는 /home/webapps 에 war 를 배포할 예정이므로 위와 같이 설정을 하였습니다....
<!--
The profile configuration
This contains required properties:
The uri to jboss-service.xml.
The uri to the deployers folder.
A list of uris to deploy folders. -->
<bean class="org.jboss.system.server.profileservice.repository.StaticProfileFactory" name="BootstrapProfileFactory">
<property name="bindingsURI">${jboss.server.home.url}conf/bindingservice.beans</property>
<property name="bootstrapURI">${jboss.server.home.url}conf/jboss-service.xml</property>
<property name="deployersURI">${jboss.server.home.url}deployers</property>
<property name="applicationURIs">
<list elementclass="java.net.URI">
<value>${jboss.server.home.url}deploy</value>
<value>file:/home/webapps</value>
</list>
</property>
<property name="attachmentStoreRoot">${jboss.server.data.dir}/attachments</property>
<property name="profileFactory"><inject bean="ProfileFactory"></inject></property>
</bean>
...
</deployment>
http://httpd.apache.org/download.cgi 에서 2.2.3 버전을 다운 받습니다.
적당한 옵션 (--prefix=/usr/local/apache2 --enable-so) 으로 configure 한 후, make, make install 로 설치를 수행합니다.
# ./configure --prefix=/usr/local/apache2 --enable-so
# make
# make install
# make
# make install
다음으로 mod_jk 를 다운 받습니다. http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/ 에서 자신의 OS 와 Apache HTTP Server 버전에 맞게 다운을 받습니다. 다운 받은 파일을 mod_jk.so 로 이름을 변경한 후, <APACHE_HOME>/modules 디렉토리에 복사합니다.
다음으로는 아파치 설정 파일을 구성합니다.
<APACHE_HOME>/conf/httpd.conf
# Include mod_jk's specific configuration file
Include conf/mod-jk.conf
파일의 맨 끝에 위와 같이 mod-jk.conf 를 include 하는 것을 추가합니다.Include conf/mod-jk.conf
<APACHE_HOME>/conf/mod-jk.conf
# Load mod_jk module
# Specify the filename of the mod_jk lib
LoadModule jk_module modules/mod_jk.so
# Where to find workers.properties
JkWorkersFile conf/workers.properties
# Where to put jk logs
JkLogFile logs/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel info
# Select the log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
# JkOptions indicates to send SSK KEY SIZE
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat
JkRequestLogFormat "%w %V %T"
# Mount your applications
JkMount /test-jboss/* loadbalancer
# You can use external file for mount points.
# It will be checked for updates each 60 seconds.
# The format of the file is: /url=worker
# /examples/*=loadbalancer
JkMountFile conf/uriworkermap.properties
# Add shared memory.
# This directive is present with 1.2.10 and
# later versions of mod_jk, and is needed for
# for load balancing to work properly
JkShmFile logs/jk.shm
# Add jkstatus for managing runtime data
<Location /jkstatus/>
JkMount status
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
웹 어플리케이션의 context-root 가 /text-jboss 이기 때문에 JkMount 에 설정하였습니다.# Specify the filename of the mod_jk lib
LoadModule jk_module modules/mod_jk.so
# Where to find workers.properties
JkWorkersFile conf/workers.properties
# Where to put jk logs
JkLogFile logs/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel info
# Select the log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
# JkOptions indicates to send SSK KEY SIZE
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat
JkRequestLogFormat "%w %V %T"
# Mount your applications
JkMount /test-jboss/* loadbalancer
# You can use external file for mount points.
# It will be checked for updates each 60 seconds.
# The format of the file is: /url=worker
# /examples/*=loadbalancer
JkMountFile conf/uriworkermap.properties
# Add shared memory.
# This directive is present with 1.2.10 and
# later versions of mod_jk, and is needed for
# for load balancing to work properly
JkShmFile logs/jk.shm
# Add jkstatus for managing runtime data
<Location /jkstatus/>
JkMount status
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
<APACHE_HOME>/conf/uriworkermap.properties
# Simple worker configuration file
# Mount the Servlet context to the ajp13 worker
/jmx-console=loadbalancer
/jmx-console/*=loadbalancer
/web-console=loadbalancer
/web-console/*=loadbalancer
/test-jboss=loadbalancer
/test-jboss/*=loadbalancer
웹 어플리케이션의 context-root 로 마운트 포인트를 설정합니다.# Mount the Servlet context to the ajp13 worker
/jmx-console=loadbalancer
/jmx-console/*=loadbalancer
/web-console=loadbalancer
/web-console/*=loadbalancer
/test-jboss=loadbalancer
/test-jboss/*=loadbalancer
<APACHE_HOME>/conf/workers.properties
# Define list of workers that will be used
# for mapping requests
worker.list=loadbalancer,status
# Define Node1
worker.node1.port=8009
worker.node1.host=192.168.0.11
worker.node1.type=ajp13
worker.node1.lbfactor=1
worker.node1.cachesize=10
# Define Node2
worker.node2.port=8109
worker.node2.host=192.168.0.11
worker.node2.type=ajp13
worker.node2.lbfactor=1
worker.node2.cachesize=10
# Load-balancing behaviour
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=1
#worker.list=loadbalancer
# Status worker for managing load balancer
worker.status.type=status
인스턴스에 해당하는 AJP 1.3 포트를 설정합니다.# for mapping requests
worker.list=loadbalancer,status
# Define Node1
worker.node1.port=8009
worker.node1.host=192.168.0.11
worker.node1.type=ajp13
worker.node1.lbfactor=1
worker.node1.cachesize=10
# Define Node2
worker.node2.port=8109
worker.node2.host=192.168.0.11
worker.node2.type=ajp13
worker.node2.lbfactor=1
worker.node2.cachesize=10
# Load-balancing behaviour
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=1
#worker.list=loadbalancer
# Status worker for managing load balancer
worker.status.type=status
이제 배포할 웹 어플리케이션의 설정만 남았습니다.
세션 복제 설정을 위해서 아래와 같이 설정합니다.
/WEB-INF/web.xml
<?xml version="1.0"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<distributable/>
</web-app>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<distributable/>
</web-app>
/WEB-INF/jboss-web.xml
<!DOCTYPE jboss-web PUBLIC
-//JBoss//DTD Web Application 5.0//EN
http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd>
<jboss-web>
<replication-config>
<!--
<cache-name>standard-session-cache</cache-name>
-->
<replication-trigger>SET</replication-trigger>
<replication-granularity>SESSION</replication-granularity>
<replication-field-batch-mode>true</replication-field-batch-mode>
<use-jk>false</use-jk>
<max-unreplicated-interval>30</max-unreplicated-interval>
<snapshot-mode>instant</snapshot-mode>
<snapshot-interval>1000</snapshot-interval>
<session-notification-policy>org.jboss.web.tomcat.service.session.notification.IgnoreUndeployLegacyClusteredSessionNotificationPolicy</session-notification-policy>
</replication-config>
</jboss-web>
use-jk element 가 true 라면 sticky session 정보가 설정되어 한번 연결이 되었던 인스턴스로 계속 요청을 보내게 됩니다. 로드밸런싱을 위해서는 false 로 설정하는 것이 좋습니다.-//JBoss//DTD Web Application 5.0//EN
http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd>
<jboss-web>
<replication-config>
<!--
<cache-name>standard-session-cache</cache-name>
-->
<replication-trigger>SET</replication-trigger>
<replication-granularity>SESSION</replication-granularity>
<replication-field-batch-mode>true</replication-field-batch-mode>
<use-jk>false</use-jk>
<max-unreplicated-interval>30</max-unreplicated-interval>
<snapshot-mode>instant</snapshot-mode>
<snapshot-interval>1000</snapshot-interval>
<session-notification-policy>org.jboss.web.tomcat.service.session.notification.IgnoreUndeployLegacyClusteredSessionNotificationPolicy</session-notification-policy>
</replication-config>
</jboss-web>
kr.co.vicki.test.jboss.UserInfo.java
/createSession.jsp
/viewSession.jsp
/createSession.jsp?id=vicki&name=vicki&empno=99999 로 요청 시
첫번째 인스턴스에서 세션이 생성되었음을 확인할 수 있습니다.
같은 브라우저에서 /viewSession.jsp 로 요청 시
인스턴스 1 에서 생성된 세션을 인스턴스 2 에서 확인할 수 있습니다.
다시 한번 요청하면 라운드 로빈 방식의 로드 밸런싱에 의해 1번 인스턴스로 요청을 하게 됩니다.
failover 테스트를 위해 인스턴스 1 을 종료하게 되면 모든 요청이 인스턴스 2 로 가게 됩니다.
이로써 클러스터링 (로드밸런싱 + failover) 테스트를 완료하였습니다.
어떻게 보면 테스트 환경은 쉽게 구성될 수 있지만, 실제로 운영환경에서는 각 설정값을 변경해주어야 재대로 성능을 발휘할 수 있습니다. 그리고 방화벽이 있는 경우 세션 복제를 위한 멀티캐스트 송수신이 정상적으로 안될 수도 있습니다.
간단한 웹 어플리케이션이 포함된 JBoss 인스턴스 하나 띄우는데 메모리가 600 메가 정도 사용하는 것 같습니다. 한 시스템에 2개의 인스턴스를 띄우려면 적어도 인스턴스당 1.5 기가의 메모리가 필요하지 않을까 생각이 됩니다.
이외에도 많은 변수가 있기에 실제 운영 환경에 배포하기 위해서는 많은 공수가 들 것으로 생각됩니다.
참고자료
http://www.jboss.org/file-access/default/members/jbossclustering/freezone/docs/cluster_guide/5.1/pdf/Clustering_Guide.pdf
http://community.jboss.org/wiki/ConfigurationChangesforClusteredWebApplicationsinAS5
http://www.datadisk.co.uk/html_docs/java_app/jboss5/jboss5_clustering.htm
Posted by
자수씨