본문 바로가기

Server/WAS

Tomcat8 - 세션 클러스터링(Session Clustering) 가이드

728x90

웹 서비스를 운영하다 보면 트래픽이 급증하거나 서버 장애가 발생하는 경우에도 안정적인 서비스를 제공하기 위해 여러 대의 서버를 사용하게 됩니다. 하지만 여러 서버를 사용할 때 생기는 가장 큰 문제 중 하나는 세션(session) 관리입니다.

사용자가 A 서버에서 로그인했는데, 갑자기 B 서버로 이동하면 다시 로그인해야 하는 문제가 발생하게 됩니다.

이때 세션 클러스터링(Session Clustering)을 이용하면 이런 문제를 해결할 수 있습니다.

 

1. 세션 클러스터링이란?

먼저 세션(Session)에 대해 잠깐 설명드리겠습니다. 웹 애플리케이션에서 사용자가 로그인하거나 장바구니에 상품을 담는 등 개인화된 데이터를 서버에 저장할 때, 이 정보를 세션에 저장합니다. 기본적으로 세션은 사용자가 접속한 서버에만 저장되기 때문에, 사용자가 다른 서버로 이동하면 그 정보가 사라질 수 있습니다.

세션 클러스터링은 여러 서버가 서로 세션 데이터를 공유하는 기술입니다. 클러스터에 속한 서버들이 서로 세션 정보를 동기화해서 사용자가 어떤 서버로 접속하더라도 동일한 세션 상태를 유지할 수 있도록 해줍니다.

즉, 사용자가 어느 서버로 이동하든 동일한 세션을 유지함으로써 로그아웃이나 장바구니 초기화 같은 불편을 없애는 기술입니다.

 

2. 세션 클러스터링을 사용하는 이유

1) 부하 분산(로드 밸런싱)

서버 하나로 많은 트래픽을 처리하기 어려울 때, 보통 여러 서버에 요청을 나누는 로드 밸런싱 기술을 사용합니다.

이때 사용자가 A 서버에서 세션을 생성했다가 B 서버로 이동해도 세션이 유지되도록 하기 위해 세션 클러스터링이 필요합니다.

2) 고가용성(서버 장애 대비)

서버 중 하나가 장애를 일으키더라도, 다른 서버가 세션 정보를 가지고 있으면 서비스가 중단되지 않고 유지됩니다.

즉, 세션 클러스터링을 통해 서버 장애에도 안정적으로 세션을 유지할 수 있어, 서비스의 가용성을 높일 수 있습니다.

 

3. 세션 클러스터링의 장단점

장점

  • 고가용성: 서버가 다운되더라도 다른 서버가 세션을 유지하므로, 사용자에게 끊김 없는 서비스를 제공합니다.
  • 유연한 확장성: 트래픽이 증가하면 새로운 서버를 추가해도 세션이 그대로 유지되므로 확장성이 좋습니다.
  • 부하 분산: 여러 서버가 세션을 공유하므로 트래픽이 분산돼 서버 부하를 줄일 수 있습니다.

단점

  • 네트워크 트래픽 증가: 서버들이 세션을 주고받기 때문에 네트워크 부하가 증가할 수 있습니다.
  • 성능 저하 가능성: 세션 복제가 잦아지면 서버 간 동기화로 인해 성능 저하가 발생할 수 있습니다.

 

4. 세션 복제 방식: 델타매니저(DeltaManager) vs 백업매니저(BackupManager)

세션 클러스터링에서는 세션 복제를 어떻게 처리할지에 따라 두 가지 방식이 있습니다. 

1) 델타매니저(DeltaManager)

델타매니저는 세션의 변경된 부분(델타)만 복제하는 방식입니다. 예를 들어, 사용자가 장바구니에 상품을 추가하면 그 추가된 부분만 복제해 다른 서버에 전송합니다. 이렇게 하면 네트워크 트래픽이 줄고 복제 속도가 빨라집니다.

그러나 이 방식은 각 서버가 변경된 부분을 합쳐서 세션을 복원해야 하기 때문에, 서버 간의 동기화가 매우 중요합니다.

2) 백업매니저(BackupManager)

백업매니저는 세션의 전체 데이터를 통째로 복제하는 방식입니다. 델타매니저처럼 부분적으로 데이터를 복제하지 않고, 세션이 변경될 때마다 모든 데이터를 그대로 다른 서버로 복제합니다. 이 방식은 설정이 덜 복잡하지만, 네트워크 부하가 더 클 수 있고 복제 속도도 느려질 수 있습니다.

 

 

반응형

 

 

5. 세션 클러스터링 설정 방법

Apache와 Tomcat을 mod_jk를 사용해 AJP 통신을 설정하고, 여러 Tomcat 서버 간에 세션 클러스터링을 설정합니다.

1) Apache와 Tomcat 연결: mod_jk 설정

먼저 Apache 웹 서버와 Tomcat 서버를 AJP를 통해 연결합니다. Apache의 workers.properties 파일을 설정합니다.

workers.properties 파일 예시

# 사용할 worker 목록을 설정
worker.list=loadbalancer

# Tomcat 1 설정 (1.1.1.1 서버)
worker.tomcat1.type=ajp13
worker.tomcat1.host=1.1.1.1
worker.tomcat1.port=8009
worker.tomcat1.lbfactor=1
worker.tomcat1.socket_timeout=60
worker.tomcat1.jvm_route=tomcat1

# Tomcat 2 설정 (1.1.1.2 서버)
worker.tomcat2.type=ajp13
worker.tomcat2.host=1.1.1.2
worker.tomcat2.port=8009
worker.tomcat2.lbfactor=1
worker.tomcat2.socket_timeout=60
worker.tomcat2.jvm_route=tomcat2

# 로드 밸런서 설정
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=tomcat1,tomcat2
worker.loadbalancer.sticky_session=true

 

각 Tomcat 서버에 대한 설정을 추가한 후, 로드 밸런싱과 세션 고정(sticky session)을 설정했습니다.

* jvmRoute는 각 Tomcat 서버에서 고유하게 설정해줘야 합니다.

2) Tomcat 클러스터 설정: server.xml

각 Tomcat 서버에서 클러스터링을 설정하기 위해 server.xml 파일에 아래와 같은 설정을 추가합니다.

예시는 Tomcat 1의 설정입니다 (유니캐스트 방식)

<Cluster 
   channelSendOptions="8" 
   channelStartOptions="3" 
   className="org.apache.catalina.ha.tcp.SimpleTcpCluster">

   <Manager 
      className="org.apache.catalina.ha.session.DeltaManager" 
      expireSessionsOnShutdown="false" 
      notifyListenersOnReplication="true"
   />

   <Channel className="org.apache.catalina.tribes.group.GroupChannel">
      <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
         <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" />
      </Sender>

      <!-- Receiver: 자신의 서버 정보 -->
      <Receiver 
         address="1.1.1.1" 
         autoBind="0" 
         className="org.apache.catalina.tribes.transport.nio.NioReceiver" 
         maxThreads="6" 
         port="3101" 
         selectorTimeout="5000"
      /> 

      <!-- 다른 서버의 정보 (서버 2) -->
      <Interceptor className="org.apache.catalina.tribes.group.interceptors.StaticMembershipInterceptor">
         <Member 
            className="org.apache.catalina.tribes.membership.StaticMember" 
            port="3101" 
            host="1.1.1.2" 
            uniqueId="{0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}" 
         /> 
      </Interceptor>
   </Channel>

   <Valve 
      className="org.apache.catalina.ha.tcp.ReplicationValve" 
      filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;
   />
	<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
</Cluster>

 

6. web.xml에서 세션 클러스터링을 활성화하기

1) <distributable> 태그의 역할

web.xml 파일에서 <distributable> 태그는 세션이 여러 대의 서버에서 공유 가능함을 나타냅니다. 각 서버에서 생성된 세션이 다른 서버로 복제될 수 있다는 것을 명시적으로 선언하는 것입니다.

이 설정이 없다면, 아무리 클러스터링 설정을 해도 세션이 다른 서버로 복제되지 않습니다. 따라서 세션 클러스터링을 설정할 때는 반드시 web.xml에 <distributable> 태그를 추가해야 합니다.

2) web.xml 설정 예시

아래는 web.xml 파일에서 <distributable> 태그를 추가한 간단한 예시입니다.

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

   <!-- 기존 web.xml 설정 -->

   <!-- 세션 클러스터링 활성화를 위한 distributable 설정 -->
   <distributable />

</web-app>

 

7. 세션 클러스터링에서 꼭 알아야 할 추가 내용

1) 세션 고정(Sticky Session)의 필요성과 장단점

세션 클러스터링 설정을 하더라도 Sticky Session을 사용하는 경우가 많습니다. 사용자가 처음 접속한 서버에 세션을 생성하면 이후에도 해당 서버로만 연결되는 방식을 의미합니다. 서버 간 세션 복제 횟수를 줄여 성능 저하를 방지합니다.

Sticky Session을 사용하는 이유는 간단합니다. 세션 복제가 필요한 경우를 최소화해 성능을 개선하려는 것입니다. 하지만 Sticky Session 방식은 장애 상황에서 문제가 될 수 있습니다. 만약 특정 서버가 장애로 다운되면 그 서버에 고정된 세션을 가진 사용자는 로그아웃 상태가 되어버립니다.

따라서 Sticky Session을 사용할지 여부는 서비스 성격에 따라 결정해야 합니다. 예를 들어, 복제에 따른 성능 이슈가 우려된다면 Sticky Session을 사용하고, 장애에 대한 민감도가 높다면 완전한 세션 클러스터링을 사용해야 합니다.

2) 세션 데이터의 크기와 성능 이슈

세션 클러스터링에서 또 하나 주의해야 할 점은 세션 데이터의 크기입니다. 세션에 저장되는 데이터가 너무 많아지면, 서버 간에 복제할 때 네트워크 트래픽이 증가하고 복제에 걸리는 시간도 길어집니다. 

대용량 데이터의 경우 세션에 저장하는 것보다 데이터베이스나 캐시 서버(Redis 등)에 저장하는 것이 좋습니다.

3) 트래픽 증가 시 대비할 확장성

웹 애플리케이션의 트래픽이 급격히 증가할 경우, 기존 서버만으로는 모든 요청을 처리하기 어려워집니다. 이때 서버를 추가로 확장하는 상황이 발생할 수 있습니다. 세션 클러스터링을 사용하면 서버를 쉽게 확장할 수 있는 장점이 있습니다.

하지만 서버를 추가할 때 세션 복제가 제대로 이루어지지 않으면 문제가 발생할 수 있습니다. 이를 방지하기 위해 새로운 서버를 클러스터에 추가할 때는 세션 동기화가 완벽히 이루어지는지 모니터링하는 것이 중요합니다. 또한, 서버 간의 네트워크 상태가 불안정하면 세션 복제에 실패할 수 있으므로 네트워크 환경도 주의 깊게 관리해야 합니다.

4) 네트워크 구성과 멀티캐스트/유니캐스트 선택

세션 복제는 서버 간 네트워크를 통해 이루어집니다. 여기서 멀티캐스트(multicast)와 유니캐스트(unicast)라는 두 가지 통신 방식 중 하나를 선택하게 됩니다. 각 방식의 차이점을 알아볼까요?

  • 멀티캐스트(multicast): 한 서버가 특정 그룹에 속한 여러 서버들에게 동시에 데이터를 전송하는 방식입니다. 이 방식은 네트워크 자원을 효율적으로 사용할 수 있지만, 모든 네트워크 환경에서 사용 가능한 것은 아닙니다.
    * 특히 클라우드 환경에서는 멀티캐스트가 지원되지 않는 경우가 많습니다.
  • 유니캐스트(unicast): 특정 서버 하나에만 데이터를 전송하는 방식입니다. 이는 멀티캐스트보다 트래픽이 더 많이 발생할 수 있지만, 네트워크 호환성이 좋고 클라우드 환경에서도 무리 없이 사용할 수 있습니다.

현대의 많은 클라우드 기반 인프라에서는 유니캐스트 방식을 주로 사용합니다. 

5) 세션 클러스터링의 모니터링과 장애 처리

세션 클러스터링이 정상적으로 동작하는지 지속적으로 모니터링하는 것은 매우 중요합니다. 특히 대규모 트래픽이 발생하거나 서버 간 통신이 불안정해질 때, 세션 복제에 실패하는 경우가 발생할 수 있습니다. 이를 예방하기 위해서 로그 모니터링, 네트워크 상태 체크애플리케이션 성능 모니터링 도구를 사용하는 것이 좋습니다.

장애가 발생했을 때 세션을 잃지 않고 복구하기 위해서는, 세션 데이터를 가능한 한 데이터베이스 또는 외부 저장소에 저장하는 방식을 병행하는 것도 방법입니다. 이를 통해 서버 간 네트워크가 불안정할 때에도 세션 데이터 유실을 방지할 수 있습니다.

728x90
반응형