본문으로 건너뛰기

16.3 웹 애플리케이션 클러스터링

웹 애플리케이션의 클러스터링은 로드 밸런싱과 세션 복제 두 가지 기능이 있다. 일반적인 구성은 다음 그림과 같다.

그림 4. 웹 애플리케이션의 클러스터링 구성

로드 밸런싱

웹 애플리케이션에서 로드 밸런싱은 웹 서버에서 요청을 여러 대의 웹 애플리케이션 서버로 분배하는 기능이다. 이러한 방법으로 여러 서버로 부하를 분산하여, 특정 서버에만 부하가 많아지지 않도록 한다. 또, 설정을 통해 특정 서버 노드에만 부하를 더 주는 것도 가능하다. JBoss EAP 6에서는 웹 서버에서 사용할 수 있는 두 가지 로드 밸런싱 방법이 제공된다.

  • mod_jk 커넥터

    mod_jk는 웹 서버에 설치하는 로드 밸런싱 모듈이다. 애플리케이션 서버와 통신에 AJP 프로토콜을 사용한다.

  • mod_cluster 커넥터

    mod_cluster는 jboss.org에서 개발되고 있는 Apache 웹 서버와 함께 구성하는 로드 밸런싱 방법이다. 옵션을 웹 서버가 아닌 JBoss에서 설정할 수 있다.

mod_jk 커넥터와 mod_cluster 커넥터에 대한 상세한 내용은 뒷장에서 설명한다.

세션 복제

로드 밸런서는 효율적인 세션의 관리를 위해 스티키(Sticky) 세션을 사용한다. 최초로 접속한 서버에 세션을 저장하고 계속 해당 서버로만 요청을 한다. 장애가 발생하여 접속한 애플리케이션 서버가 정지해 버리면, 로드밸런스는 다른 서버로 요청을 다시 전송한다. 이때, 요청을 받은 서버에 장애가 발생한 서버에서 생성된 세션 정보가 없으면 더 이상 처리할 수 없다. 일반적으로 세션에는 로그인 정보가 포함되어 있는데, 페일오버 되었을 경우 세션 정보가 없으면 로그아웃된 것으로 인식한다. 이러한 경우를 대비하여 세션 정보를 미리 다른 서버에 전송하고 동기화한다. 이런 기능이 세션 복제이다.

세션 복제 시 주의점

  • 클러스터의 SPOF(Single Point Of Failure)를 방지하려면 세션을 하나 이상의 다른 서버에 복제해야 한다.
  • HTTP 세션에 저장되는 값은 직렬화(Serializable)된 값이어야 한다.
  • 멀티캐스트 주소가 같으면 같은 클러스터로 묶이게 된다. 서로 다른 서비스는 서로 다른 멀티캐스트 주소를 사용해야 한다.
  • 성능을 위해서는 내부 클러스터링용으로 별도의 NIC를 사용하는 것이 좋다.

세션 복제 설정 방법

웹 애플리케이션에서 세션 클러스터링을 구성할 때 목적에 따라 적합한 로드 밸런스 모듈과 세션 복제 방법을 결정해야 한다.

구분설명
mod_jk를 이용한 로드 밸런싱로드밸런싱은 기본적으로 웹 서버에서 제공되는 기술이다. mod_jk 로드 밸런싱을 사용하려면, JBoss EAP 6에서는 AJP 커넥터 설정만 하면 된다. ha, full-ha 프로파일에 AJP 커넥터가 설정되어 있다. mod_jk는요청 수나 세션 수를 기반으로 로드 밸런스할 수 있고, Cookie를 이용한 부하분산 설정도 가능하다. 또, 세션유지 관리를 위한 스티키(Sticky) 세션 기능도 제공한다.
mod_cluster를 이용한 로드 밸런싱mod_cluster 로드밸런싱을 사용하려면, 웹 서버의 설정뿐만 아니라 JBoss EAP 6의 mod_cluster도 설정해야 한다. ha, full-ha 프로파일에 modcluster 서브시스템이 설정되어 있다. mod_cluster는 CPU 부하나 메모리 상황 등에 따라 동적으로 로드 밸런싱 할 수 있다. JBoss 인스턴스 자동 등록, 동적으로 부하를 계산하여 로드 밸런싱하는 등 클라우드 환경를 지원하기 위한 많은 기능을 제공한다. mod_cluster와 애플리케이션 서버간 통신에는 AJP 프로토콜뿐만 아니라 HTTP, HTTPS 프로토콜도 사용할 수 있고, 스티키(Sticky) 세션도 지원한다.

표 2. 로드 밸런싱 모듈 비교

ha, full-ha 프로파일에는 세션이 복제되도록 설정되어 있기 때문에, 이 프로파일을 사용하는 JBoss EAP 6 인스턴스를 여러 개 기동하면, 자동으로 클러스터를 구성하여 세션을 복제한다.

22:55:56,248 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 56) JBAS010281: Started default-host/session cache from web container
22:55:56,255 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 55) JBAS010281: Started repl cache from web container
22:55:56,264 INFO [org.jboss.as.clustering] (MSC service thread 1-2) JBAS010238: Number of cluster members: 2

실제 세션이 복제되려면, 웹 애플리케이션에 세션을 복제하겠다는 설정이 필요하다. 웹 애플리케이션의 설정이 없으면 ha 프로파일을 사용하여 클러스터링이 구성되어 있어도, 세션은 복제되지 않는다. 웹 애플리케이션에 세션을 복제하겠다는 설정은 web.xml 파일에 <distributable/> 태그를 추가하면 된다.

다음은 web.xml에 <distributable/>을 추가한 예이다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>session</display-name>
<distributable/>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

이외에는 일반 웹 애플리케이션을 작성하는 방법과 같다.

세션 복제 상세설정

WEB-INF/jboss-web.xml 파일에서 세션 복제에 대한 상세한 설정을 지정할 수 있다. 다음은 세션 설정의 예이다.

<jboss-web>
<context-root>/</context-root>
<replication-config>
<cache-name>custom-session-cache</cache-name>
<replication-trigger>SET</replication-trigger>
<replication-granularity>ATTRIBUTE</replication-granularity>
<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>com.example.CustomSessionNotificationPolicy</session-notification-policy>
</replication-config>
</jboss-web>

세션이 언제 복제될 것인지를 <replication-trigger>를 사용하여 설정할 수 있다. 사용할 수 있는 옵션은 다음과 같다.

  • SET : 세션이 설정될 때 복제
  • SET_AND_GET : 세션을 읽기만 해도 복제
  • SET_AND_NON_PRIMITIVE_GET : 세션이 설정될 때와 Java의 Primitive 타입이 아닌 타입은 읽을 때도 복제. 기본 설정값.

또, <replication-granularity>를 사용하여 세션 복제 범위를 지정할 수 있다. 기본값은 SESSION으로 세션에 보관된 객체 전체를 복제한다. 애트리뷰트 (attribute)를 사용하면 세션 객체 중 변경된 애트리뷰트 (attribute)만 복제하기 때문에 세션 복제 속도를 크게 향상할 수 있다.

세션 타임아웃 설정

HTTP 프로토콜은 연결되지 않은 상태로 통신하기 때문에 브라우저의 쿠키와 서버의 세션을 사용하여 서로의 상태를 유지한다. 연결되지 않은 상태이기 때문에 사용자가 웹 애플리케이션을 계속 사용하고 있는지 판단할 수 없다. 그래서 지정된 시간 동안 세션을 사용하지 않으면, 그 세션을 삭제하는 세션 타임아웃 기능을 사용한다. 웹 애플리케이션의 세션 타임아웃은 web.xml 파일의 <session-config>에서 설정한다. jboss-web.xml 파일에서도 세션 타임아웃값을 다음과 같이 설정할 수 있다.

<jboss-web>
<session-config>
<session-timeout>120</session-timeout>
</session-config>
</jboss-web>

세션 Passivation

세션에 너무 많은 데이터가 들어 있으면 어떻게 될까? 세션은 기본적으로 메모리, 즉 Java의 Heap메모리를 사용하기 때문에 OutOfMemory 오류가 발생할 수 있다. 그래서 기본적으로 세션에는 최소한의 값만 저장하는 것이다.

하지만 이미 개발된 애플리케이션을 수정하기 어렵다면 이런 방법을 사용할 수 있다.

패시베이션(Passivation)은 자주 사용되지 않는 세션을 메모리에서 삭제하고 디스크에 저장하여 메모리를 효율적으로 사용하는 방법이다. 반대로 액티베이션(Activation)은 디스크에 저장된 데이터를 메모리에 읽어 들이는 것을 말한다.

HTTP 세션의 패시베이션은 다음 3가지 상황에서 발생한다.

  • 새로운 세션을 만들려고 할 때, 이미 최대 액티브 세션 수를 넘었기 때문에 서버는 세션 일부를 디스크에 저장하고 새 세션을 만든다.
  • 주기적으로 백그라운드 작업을 통해 세션을 디스크에 저장한다.
  • 웹 애플리케이션이 배포되어 있고 새로 배포되는 웹 애플리케이션의 세션 관리자가 다른 서버의 세션 백업 본을 가져오는 경우에 세션이 패시베이션 될 수 있다.

세션 패시베이션 설정

세션 패시베이션은 애플리케이션 WEB_INF/jboss-web.xml 파일에 설정한다.

<jboss-web>
<max-active-sessions>20</max-active-sessions>
<passivation-config>
<use-session-passivation>true</use-session-passivation>
<passivation-min-idle-time>60</passivation-min-idle-time>
<passivation-max-idle-time>600</passivation-max-idle-time>
</passivation-config>
</jboss-web>

세션 패시베이션 설정 항목들은 다음과 같다.

구분설명기본값
<max-active-sessions>허용되는 세션의 최대 수. 패시베이션을 사용할 때 세션 수가 이 값을 초과하면 설정된 <passivation-min-idle-time>을 초과한 세션들이 저장된다. 그래도 허용 세션 수를 제한을 초과하면 새로운 세션을 만들지 못한다.-1 (제한없음)
<use-session-passivation>세션 패시베이션을 사용할 것인지 설정false
<passivation-min-idle-time>최대 세션 수를 유지하기 위해 패시베이션될 때 이 시간만큼 사용되지 않은 세션이 대상이 된다.-1
<passivation-max-idle-time>지정된 시간 이상 사용되지 않은 세션이 패시베이션 된다. 최대 세션 수와 상관없이 지정된 시간이 되면 패시베이션 된다. web.xml의 <session-timeout> 설정보다 작은 값으로 설정해야 한다.-1

표 3. 패시베이션 설정 항목

쿠키 도메인

쿠키 도메인은 애플리케이션을 사용하는 클라이언트의 웹 브라우저에서 쿠키를 읽을 수 있는 호스트를 지정하는 방법이다. 쿠키 도메인의 기본값은 ‘/’ 이다. 기본적으로 쿠키를 만든 호스트에서만 쿠키의 내용을 읽을 수 있다. 다른 호스트에서도 쿠키의 내용을 읽을 수 있게 하려고 쿠키 도메인을 설정한다.

예를 들어 SSO(Single Sign On)을 사용하여 로그인 정보를 공유하기 위해 SSO 밸브를 사용하여 쿠키 도메인을 설정하는 방법을 살펴보자. 다음 설정은 다른 서버에서 실행되는 서로 다른 애플리케이션이 http://app1.opennaru.comhttp://app2.opennaru.com 에서 SSO 컨텍스트를 공유할 수 있는 설정이다.

쿠키 도메인 설정 예

<Valve className="org.jboss.web.tomcat.service.sso.ClusteredSingleSignOn"

cookieDomain="opennaru.com"/>

TCP 클러스터링 방법

jgroups 서브시스템의 default-stacktcp로 변경하면 멀티캐스트가 아닌 TCP를 사용한다고 설명했다. 하지만 멀티캐스트가 전혀 동작하지 않는 아마존 웹 서비스(AWS)와 같은 환경에서는 이 설정만으로는 동작하지 않는다.

그 이유는 tcp 스택으로 변경하더라도 tcp 스택에 클러스터 멤버를 찾기 위한 PING 프로토콜로 멀티캐스트를 사용하는 MPING을 사용하도록 설정되어 있기 때문이다.

<protocol type="MPING" socket-binding="jgroups-mping"/>

멀티캐스트를 사용하지 않는 PING 프로토콜로 변경해야 한다. 멀티캐스트를 사용하지 않는 경우에는 TCPPING, FILE_PING, S3_PING, TCPGOSSIP, JDBC_PING등 다양한 PING 프로토콜들이 있다. 이 방법 중 다음에서 TCPPING 설정방법을 살펴보자.

다음과 같이 TCPPINGinitial_hosts 프로퍼티로 호스트의 IP와 포트를 지정하면 된다. 시스템 프로퍼티로 값을 변경할 수 있도록 값을 설정하였다.

<subsystem xmlns="urn:jboss:domain:jgroups:1.1" default-stack="tcp">

… 생략 …

<stack name="tcp">
<transport type="TCP" socket-binding="jgroups-tcp"/>
<protocol type="TCPPING">
<property name="initial_hosts">${jgroups.tcpping.initial_hosts:192.168.0.11[7600],192.168.0.11[7700], 192.168.0.12[7600],192.168.0.12[7700]}</property>
<property name="port_range">0</property>
<property name="timeout">3000</property>
<property name="num_initial_members">3</property>
</protocol>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>