본문 바로가기

서버운영 (TA, ADMIN)/분산처리

[분산처리] WAS 이중화와 세션클러스터링

WAS 이중화 방법 및 세션 클러스터링


 

로드밸런싱 방법에는 크게 두가지가 있습니다. 하나는 L4를 이용한 웹서버 로드밸런싱, 그리고 나머지는  WAS 로드밸런싱입니다. L4를 이용한 로드 밸런싱은 하드웨어 영역까지 컨트롤해야 하기때문에 상당히 난이도 있는 기술이라고 할 수 있지만, WAS 로드밸런싱은 아파치에서 제공하는 모듈을 이용하여 조금더 간단하게 설정할 수 있습니다. 일단 여기서 말하는 아파치는 WEB 서버이며, 톰캣에서 로드밸런싱을 지원하지는 않습니다. AJP를 통한 로드밸런싱은 Tomcat의 부하증가나 이중화시에 이용할수 있습니다.

 

아파치 모듈 중에는 mod_jk, mod_proxy을 이용해서 이중화를 해주는 것이 가능합니다. L4 로드밸런싱 방법은 HAProxy 같은 소프트웨어 혹은 L4 하드웨어 등으로 이중화가 가능하기도 합니다. 만약 한 session time 동안 한 WAS에 지속적으로 접속하고 싶게 하려면 sticky session 기능을 활성화 시키면 됩니다.

 

sticky session을 이용하면 한 클라이언트의 세션 트랜잭션 작업은 한 서버에서만 일어나기때문에 이중화된 다른 서버에 해당 사용자의 세션이 없더라도 이용에 문제가 생기지 않습니다. 하지만 이때 서버 한대에 장애가 발생하면 도중에 다른 서버로 접속을 하게 되기 때문에 세션 정보가 없어 문제가 발생할 수 있습니다. 그래서 Tomcat의 기능중 에는 세션 복제(세션 클러스터) 기능을 켜두면 이중화된 톰캣 간에 multicast 방식으로 공유하고 싶은 정보의 전파가 가능하게 됩니다. 하지만 이 기능이 서로 다른 톰캣에 반영되는데에는 생각보다 시간이 오래 걸립니다. 어쨌든 결론적으로 한쪽 톰캣에 세션이 없더라도 세션을 갖고있는 다른 톰캣과 공유를 할 수 있게 됩니다.

 

 

AJP를 통한 로드밸런싱


httpd.conf 설정 파일내에 mod_jk 설정 파일 정보를 추가합니다.

 

Include conf/mod_jk.conf

 

 

실제 mod_jk.conf 파일 안에는 다음과 같은 설정을 해줍니다.

 

LoadModule jk_module modules/mod_jk.so

JkWorkersFile "conf/workers.properties"

JkLogFile logs/mod_jk.log

JkLogLevel error

JkMount /- loadbllance

 

 

그리고 상세한 로드밸런싱 설정을 하는 workers.properties 파일 입니다.

 

worker.list=tomcat1,tomcat2,loadballance

worker.tomcat1.type=ajp13

worker.tomcat1.host=localhost

worekr.tomcat1.port=9006

worker.tomcat1.lbfactor=100             # 반드시 '0'보다 커야하며, 이것은 job에 대한 비율

worker.tomcat1.socket_timeout=1800  # 30분

worker.tomcat1.recycle_timeout=1800

worker.tomcat1.cache_timeout=1800

worker.tomcat1.socket_keepalive=1     # 사용:1, 미사용:0

worker.tomcat1.connection_pool_timeout=600

 

worker.tomcat2.type=ajp13

worker.tomcat2.host=localhost

worker.tomcat2.port=9007

worker.tomcat2.lbfactor=100

worker.tomcat2.socket_timeout=1800  # 30분

worker.tomcat2.recycle_timeout=1800

worker.tomcat2.cache_timeout=1800

worker.tomcat2.socket_keepalive=1     # 사용:1, 미사용:0

worker.tomcat2.connection_pool_timeout=600

 

# tomcat timeout에 따른 중복 발생 방지

worker.loadballance.retries=0

worker.tomcat1.retries=0

worker.tomcat2.retries=0

worker.tomcat1.socket_timeout=60

worker.tomcat2.socket_timeout=60

 

worker.loadballance.type=lb

# sticky방식은 일정 시간(session time)동안 한 WAS에 지속적으로 접속하는 설정임

# 사용: true OR 1, 미사용: false OR 0

worker.loadballance.sticky_session=1

worker.loadballance.balanced_workers=tomcat1, tomcat2

 

 

그리고 tomcat1, tomcat2 각각의 server.xml 파일에 아래와 같은 설정을 추가합니다.

 

<Connector port="9006" maxHttpHeaderSize="8192" maxKeepAliveRequests="-1"

maxThreads="1000" minSpareThreads="500" maxSpareThreads="500"

enableLoopups="false" redirectPort="8443" acceptCount="500"

compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla.graviata"

compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css"

connectionTimeout="600000" disabledUploadTimeout="true" Server=""

protocol="AJP/1.3" />

<Engine jvmRoute="tomcat1" name="Catalina" defaultHost="localhost">

 

<Connector port="9007" maxHttpHeaderSize="8192" maxKeepAliveRequests="-1"

maxThreads="1000" minSpareThreads="500" maxSpareThreads="500"

enableLookups="false" redirectPort="8443" acceptCount="500"

compression="on" compressionMinSize="2048"

no CompressionUserAgents="gozilla.graviata"

compressableMimeType="text/html,text.xml,text/plain,text/javascript,text/css"

connectionTimeout="600000" disabledUploadTimeout="true" Server=""

protocol="AJP/1.3" />

<Engine jvmRoute="tomcat2" name="Catalina" defaultHost="localhost">

 

위의 server.xml에서 Server=""은 보안을 위하여 아파치 정보 유출을 막습니다. 그리고 일반적으로 Apache 프로세스보다 Tomcat 프로세스를 많이 잡아두는 것이 좋습니다. 그리고 Engine 엘리먼트의 jvmRoute 어트리뷰트는 workers.properties에서 입력한 worker의 이름을 입력해야합니다. 즉, workers.properties에서 설정한 대로, tomcat1, tomcat2롤 각각 was를 설정합니다.

 

 

 

Session Clustering 톰캣 환경 설정


세션 클러스터링 설정은 톰캣에서 지정하는 것으로 Tomcat 버전에 따라 설정 방법이 다릅니다. 각 버전에 따른 설정 방법은 tomcat 레퍼런스 사이트에서 확인 가능합니다. 일단 server.xml 파일 내, Cluster라는 단어를 검색하고 주석으로 되어있는 Cluster 엘리먼트에서 주석을 제거합니다.

 

 

 

 

AJP(Apache JServ Protocol)와 mod_jk


AJP는 웹서버 뒤에 있는 어플리케이션 서버로부터 웹서버로 들어오는 요청을 위임할 수 있는 바이너리 프로콜입니다. 어플리케이션 서버로 핑을 할 수 있는 웹서버의 모니터링 기능을 지원합니다.

 

웹개발자들은 대체로 AJP를 여러 웹서버로부터 여러개 어플리케이션 서버로의 로드밸런스 구현에 이용합니다. 세션들의 각각의 애플리케이션 서버 인스턴스의 이름을 갖는 라우팅 메커니즘을 사용하는 현재 어플리케이션 서버로 리다이렉트됩니다. 이 경우 어플리케이션 서버를 위한 리버스 프록시로 웹서버로 동작합니다.

 

AJP는 mod_jk를 사용하는 Apache HTTP Server 1.x와 Proxy AJP를 사용하는 Apache 2.x와 mod_proxy와 proxy 밸런서 모듈에서 같이 실행됩니다. 아직 릴리즈 되지 않은 lighthttpd 1.5 버전과 nginx, grizzly 2.1 그리고 iis에도 사용할 수 있습니다. 또 AJP는 Jetty 서블릿 컨테이너로 동작하는 Apache Tomcat Servlet 컨테이너에도 사용할 수 있습니다.

 

 

아파치와 톰캣이 연동하기 위해선 AJP를 통해 서로 통신을 하여야 합니다. AJP란, 아파치가 웹서버와 외부서비스(톰캣)을 연동하기 위해 정한 규약(프로토콜)입니다. 아파치는 이를 사용하여 포트 80으로 들어오는 요청은 자신이 받고, 이 요청 중 서블릿을 필요로 하는 요청은 톰캣에 넘겨 처리합니다.

 

아파치, 톰캣 연동을 위해 mod_jk라는 모듈을 사용하는데, 이는 AJP 프로토콜을 사용하여 톰캣과 연동하기 위해 만들어진 모듈입니다. mod_jk는 톰캣의 일부로 배포되지만, 아파치 웹서버에 설치하여야 합니다.

 

 

1. 아파치 웹서버의 httpd.conf에 톰캣 연동을 위한 설정을 추가하고 톰캣에서 처리할 요청을 지정.

2. 사용자의 브라우저는 아파치 웹서버(보통 포트 80)에 접속해 요청.

3. 아파치 웹서버는 사용자의 요청이 톰캣에서 처리하도록 지정된 요청인지 확인 후, 톰캣에서 처리해야 하는 경우 아파치 웹서버는 톰캣의 AJP포트(보통 8009포트)에 접속해 요청을 전달.

4. 톰캣은 아파치 웹서버로부터 요청을 받아 처리한 후, 처리 결과를 아파치 웹서버에 되돌려 준다.

5. 아파치 웹서버는 톰캣으로부터 받은 처리 결과를 사용자에게 전송.

 

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

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

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="4000(각 톰캣마다 다르게설정)"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <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"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <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.JvmRouteSessionIDBinderListener">
          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener">
        </Cluster>

 

Session Clustering의 상세한 내용은 http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html 에서 확인가능합니다. 만약 was1과 was2가 동일한 장비에서 실행되었다면, 위 설정 내용중 Reiver의 port만 구별할 수 있도록 설정하면 됩니다. (Multicast address와 port는 변경할 필요가 없습니다)

 

마지막으로 Web Application의 web.xml에 해당 Application이 클러스터링을 지원할 수 있도록 distributable Element를 입력해야 합니다. Session-Clustering에 대해 참고해야 할 사항은, HTTP Session에 저장되는 모든 Instance는 java.io.Serializable을 implements해야 한다는 점입니다. 이는 네트워크를 통해 해당 instance가 전달되어야 하기 때문이며, 만약 Serializable을 implements하지 않은 Class의 instance를 Session에 적재한다면 Clustering이 되지 않습니다.

 

 

 

https://okky.kr/article/283359

 

https://groups.google.com/forum/#!topic/ksug/6ZA6hDJOdKA

 

http://www.gnujava.com/board/article_view.jsp?article_no=647&board_no=6&table_cd=EPAR02&table_no=02

 

https://open.egovframe.go.kr/nforges/qna/qna/1372/.do

 

http://xperjune.tistory.com/entry/Tomcat-Session-Clustering-%EC%84%A4%EC%A0%95