[컴][웹] Tomcat clustering

Clustering/Session Replication HOW-TO / 톰캣에서 클러스터링 / 세션 복사 / session replication



clustering 설정 방법


  1. server.xml : <Host> 나 <Engine> 아래에 <Cluster> 설정 추가
  2. context.xml : 기본적으로 <Cluster> 아래에 설정을 하는데, 내 경우에 동작을 제대로 안해서 context.xml 에 <Manager> 부분을 옮겨놨다.


이 포스트의 내용은 ref.1 의 번역이 대부분이다.

------

고려할 사항

같은 subnet 에 있어야 하며, subnet 에서 multicast broadcast 를 지원해야 한다.
HTTP session data is replicated among the nodes in the cluster using a multicast broadcast. All nodes in the cluster must be on the same physical subnet and multicast broadcast must be supported by that subnet.[ref. 6]

Session 복사 사용


<Engine> 또는 <Host> 안에 아래 사항을 추가하자. <Engine>, <Host> 는 server.xml 에서 찾을 수 있다.

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

위의 configuration 을 추가하면 DeltaManager 를 이용하는 all-to-all session 복사(replication) 을 활성화 하게 된다. DeltaManager 는 session 간의 차이점(deltas) 을 복사하기위해 사용된다.

all-to-all 의 뜻은 cluster 에 있는 있는 모든 node 들이 같은 session 의 복사본을 갖고 있게 되는 것을 이야기 한다.

이건 cluster 규모가 작을 때 잘 동작한다. 많은 tomcat node 들이 있는 큰 cluster 에는 추천하지 않는다.

Delta manager 를 이용하면 이 manager 는 배포된 application 이 없는 node 에도 session 을 복사해 주게 된다.

이 문제를 해결하기 위해서 BackupManager 를 사용할 수도 있다. 이 manager 는 단지 session data 를 한개의 backup node 에만 복사 해 주고, application 이 배포된 node 에만 복사해 준다.
그런데, 이 BackupManager 는 Delta Manager 만큼 test 가 되어 있진 않다.

간단한 기본 설정은 여기를 참고하자.



Session 복사를 사용하기 위한 조건

Tomcat 7.0 container 에서 session 복사를 하려면 아래의 사항을 만족해야 한다.

  • 모든 session 속성에 들어가는 모든 class들은 java.io.Serializable 을 implement 해야 한다.
  • server.xml 에 Cluster element 의 주석처리를 없애자.
  • 만약 custom cluster valve 가 있으면, server.xml 에 Cluster element 아래에 ReplicationValve 가 정의되어 있어야 한다.
  • Tomcat instance 들이 같은 machine 에 있으면, tcpListenPort 속성이 각 instance 마다 고유한 값을 갖도록 해줘야 한다. 대부분의 경우에는 Tomcat 이 알아서 4000-4100 사이의 port 중 사용가능한 녀석을 찾는다.
  • web.xml 에 <web-app> 밑에 <distributable/> element 가 있어야 한다.
  • mod_jk 를 사용하면, jvmRoute 속성이 Engine element 에 있어야 하고,
    <Engine name="Catalina" jvmRoute="node01" >
    jvmRoute 속성 값은 workers.properties 에 있는 worker 이름과 같아야 한다.
  • 모든 node 가 같은 시간을 갖게 하고 NTP(Network Time Protocol) service 와 sync 돼야 한다.
  • loadbalancer 가 sticky session 모드로 설정돼야 한다.


session 은 cookie 에 의해 추적되기 때문에 밖에서 같은 URL 로 cluster 에 접근해야 한다. 그렇지 않으면 새로운 session 이 만들어 진다.

logging

Cluster 모듈은 Tomcat JULI logging framework 를 사용하기 때문에 logging.properties 를 통해 설정할 수 있다.
message 를 추적하려면, logging 에서 org.apache.catalina.tribes.MESSAGES key 부분을 enable 하면 된다.

ref. 3 에 log 설정하는 부분이 나와 있다.



Overview

tomcat 에서 session 복사를 하는 방법은 3가지가 있다. 전부 같은 효과를 갖는다.
  1. session persistence 를 사용하고, shared file system 에 session 을 복사(PersistenceManager + FileStore)(ref. 4 참고)
  2. session persistence 를 사용하고, shared databse 에 session 을 복사(PersistenceManager + JDBCStore)(ref. 4 참고)
  3. in-memory-replication 을 사용, Tomcat 과 함께 배포되는 SimpleTcpCluster 를 이용하는 것(lib/catalina-tribes.jar + lib/catalina-ha.jar)


all-to-all replication 은 cluster 가 작을 때만 효과적이다.

큰 규모의 cluster 에서는 primary-secondary session 복사(하나의 backup server 에만 session 이 저장되는 방법) 를 사용하기 위해서 간단하게 BackupManager 를 설정하자.

최근에는 DeltaManager 를 이용해서 좀 더 scalable 한 cluster solution 을 갖게되는 가능성과 함께 cluster partition들을 만들기 위해 domain worker 속성(mod_jk > 1.2.8) 을 이용할 수 있다.(이것을 위해서는 domain interceptor 를 설정해야 한다.)

all-to-all 환경에서 network traffic 을 낮게 유지하기 위해서는 cluster 를 여러개의 작은 그룹으로 나눌 수 있다.
이것은 각 group 마다 다른 multicast 주소들을 사용해서 간단하게 만들 수 있다.

        DNS Round Robin
               |
         Load Balancer
          /           \
      Cluster1      Cluster2
      /     \        /     \
  Tomcat1 Tomcat2  Tomcat3 Tomcat4
참고로, session 복사는 단지 clustering 의 시작부분일 뿐이다. cluster를 구현하는 다른 유명한 개념이 farming 이다. 이 farming 은 한 서버에 배포(deploy) 하면, cluster 가 cluster 전체에 deploy 를 해주게 된다. FarmWarDeployer 를 이용해서 이것을 할 수 있다.


Cluster 정보

Membership 은 multicast heartbeats 를 이용해서 만들어진다. 그래서 cluster 를 나누고 싶으면 <Membership> element 에서 multicast IP address 를 바꾸거나, port 를 바꾸면 된다.

heartbeat

heartbeat 에는
  • Tomcat node 의 IP address
  • Tomcat 이 replication traffic 을 listen 하는 TCP port

이 들어가 있고, 모든 data 통신은 TCP 위에서 이뤄진다.


ReplicationValve 

ReplicationValve 는 언제 request 가 complete 되고, 복사(replication)가 시작됐는지 알아내기 위해 사용된다.

ReplicationValve 는 HTTP request 마지막에 cluster 에게 notification 을 준다. cluster 가 data 를 복사할지 여부를 결정할 수 있다.

data 는 session 이 바뀔 때(setAttribute or removeAttribute 를 호출할 때)만 복사된다.

성능상 중요하게 고려할 것이 synchronous 복사 와 asynchronous 복사이다.
synchronous replication mode 에서는 request 는 복사된 session 이 전달돼서 모든 다른 node 에서 다시 초기화될 때 까지 return 되지 않는다. 그래서 request 가 return 될 때 session 이 복사된 것을 보장해 줄 수 있다.

이 mode 의 선택은 <Cluster>의 channelSendOptions 속성을 통해 결정할 수 있다. 기본값은 8 이다. SimpleTcpCluster/DeltaManager combo 로 asynchronous 이다.



<Manager> 의 위치

ref. 5 에 보면 Manager 를 <Context> 에 넣어서 override 할 수 있다고 한다. 나의 경우에도 server.xml 의 <Host> 안에 Manager 를 넣은 경우에는 동작하지 않았지만, /tomcat/conf/context.xml 안에 Manager 를 넣어주니 잘 동작했다.(ref. 5 참고)

의심이 가는 부분은
webapp/META-INF/context.xml
부분에 Context element 를 정의하고 Resource element 를 넣어줬는데, 여기서 정의한 Context element 때문일 수도 있지 않을까 생각하지만, 근거는 없다.

server.xml 의 <Host> 안에도 넣을 수 있다고 하는데 여기를 참고 하면 될 듯 하다.




번역중....




설정 예

conf/context.xml

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

conf/server.xml

<Engine>
  ...
  <Host>
  ...
    <!-- for Session Replication -->
    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="6">
            <Channel className="org.apache.catalina.tribes.group.GroupChannel">
                    <Membership className="org.apache.catalina.tribes.membership.McastService"
                                address="228.0.0.5"
                                port="45555"
                                frequency="500"
                                dropTime="3000"/>
                    <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                              address="103.130.222.132"
                              port="4000"
                              selectorTimeout="5000"
                              maxThreads="12"/>
                    <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
                            <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
                    </Sender>
                    <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
                    <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
                    <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
            </Channel>
            <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                   filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
            <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                      tempDir="/tmp/war-temp/"
                      deployDir="/tmp/war-deploy/"
                      watchDir="/tmp/war-listen/"
                      watchEnabled="false"/>
            <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
    </Cluster>
    <!-- /for Session Replication -->


References

  1. Apache Tomcat 8 (8.0.15) - Clustering/Session Replication HOW-TO
  2. ::: X2Framework Opensource Community :::
  3. Debug Tomcat Cluster | Middleware Technology Quest
  4. Tomcat Clustering Series Part 3 : Session Replication | Ramki Java Blog
  5. java - Tomcat's Clustering / Session Replication not replicating properly - Stack Overflow
  6. Apache Geronimo v2.1 Documentation: Tomcat Native Clustering

댓글 없음:

댓글 쓰기