Tomcat 5에서의 클러스터링과 로드 밸런싱, Part 2 下편


Tomcat 5에서의 클러스터링과 로드 밸런싱, Part 2 下편

클러스터 설정

"clusterapp"라고 불리는 예제 웹 어플리케이션은 클러스터 내에서 실행하기 위해 만들어졌다. 세션 복제를 최적화하기 위해 모든 인스턴스는 같은 디렉토리 구조와 컨텐츠를 가진다.
클러스터 내의 톰캣 서버 인스턴스는 세션을 전송하기 위해 IP 멀티캐스트를 사용하기 때문에, 우리는 IP 멀티캐스트가 클러스터가 설정된 머신에 사용가능한지 확인할 필요가 있다. 이것을 검증하기 위해, Tomcat: The Definitive Guide 책에서 제공하는MulticastNode라는 예제 자바 프로그램을 실행하거나 또는 멀티캐스트 서버와 클라이언트 프로그램을 작성하는 법에 관해 자바 소프트 웹 사이트에서 구할 수 있는 예제 튜토리얼을 참조하라.
클러스터 노드가 시작될 때, 클러스터 내의 다른 멤버들은 새로운 멤버가 클러스터에 추가됐다는 로그 메세지를 서버 콘솔에 보여준다. 비슷하게, 클러스터 노드가 다운될 때, 나머지 멤버들은 클러스터에서 멤버가 제거됐다는 로그 메세지를 콘솔에 보여준다. Figure 4는 클러스터 노드가 클러스터에서 제거되거나 또는 새로운 멤버가 클러스터에 추가됐을 때, 톰캣 콘솔의 로그 메세지를 보여준다.
Figure 4
Figure 4. 클러스터에서 멤버가 추가되거나 제거됐을 때의 로그 메세지
톰캣 서버에서 클러스터링과 세션 복제를 사용하기 위해 아래의 절차를 따라라:
  1. 세션에 저장할 모든 객체는 java.io.Serializable 인터페이스를 구현해야 한다.
  2. server.xml 파일의 Cluster 요소의 주석을 제거하라. Cluster 요소의 useDirtyFlag와 replicationMode는 빈도수와 세션 복제 메카니즘의 최적화를 위해 사용된다.
  3. server.xml 파일의 Valve 요소의 주석을 제거함으로써 ReplicationValve를 활성화시켜라. 만약 세션이 웹 클라이언트에 의해 변경된다면 ReplicationValve는 HTTP 리퀘스트를 인터셉트하고 클러스터 멤버들 사이의 세션 데이터를 복제하기 위해 사용된다. Valve 요소는 세션을 변경할 수 없는 리퀘스트(HTML 페이지나 이미지 파일과 같은)를 걸러내기 위해 사용할 수 있는 "filter" 속성을 가지고 있다.
  4. 단일 머신에서 3개의 톰캣 인스턴스가 실행되고 있기 때문에, tcpListenPort 속성은 각 톰캣 인스턴스에 대해 유니크하게 설정된다. mcastXXX로 시작하는 속성들 (mcastAddrmcastPortmcastFrequencymcastDropTime)은 클러스터 멤버쉽 IP 멀티캐스트 핑을 위한 것이고, tcpXXX로 시작하는 속성들(tcpThreadCounttcpListenAddresstcpListenPorttcpSelectorTimeout)은 TCP 세션 복제를 위한 것이라는 것을 아는 것은 중요하다. (아래의 "클러스터링 설정 파라미터" 테이블은 클러스터링을 사용하기 위해 톰캣 서버 인스턴스들의 설정이 어떻게 다른지 보여준다.)
  5. web.xml 메타 파일(clusterappWEB-INF 디렉토리에 위치)은  요소를 가져야 한다. 특정 웹 어플리케이션에 대해 세션 상태 복제를 하기 위해, distributable 요소는 어플리케이션을 위해 정의될 필요가 있다. 이것은 세션 복제를 필요로 하는 웹 어플리케이션이 하나 이상이라면, 모든 웹 어플리케이션의 web.xml 파일에 distributable 를 추가할 필요가 있다는 것을 의미한다. Tomcat: The Definitive Guide 책의 톰캣 클러스터링 챕터는 이 주제에 대해 매우 훌륭하게 설명하고 있다.
Table 2. 클러스터링 설정 파라미터
Configuration ParameterInstance 1Instance 2Instance 3Instance 4
Instance TypeLoad BalancerCluster Node 1Cluster Node 2Cluster Node 3
Code nameTC-LBTC01TC02TC03
Home Directoryc:/web/tomcat50c:/web/tomcat51c:/web/tomcat52c:/web/tomcat53
Server Port800590051000511005
Connector808090801008011080
Coyote/JK2 AJP Connector800990091000911009
Cluster mcastAddr228.0.0.4228.0.0.4228.0.0.4228.0.0.4
Cluster mcastPort45564455644556445564
tcpListenAddress127.0.0.1127.0.0.1127.0.0.1127.0.0.1
Cluster tcpListenPort4000400140024003
주: 모든 클러스터 멤버는 동일한 물리적 머신에서 실행되고 있기 때문에, 같은 IP 주소를 사용한다 (127.0.0.1).
톰캣 인스턴스를 시작하고 중지하기 위해 Ant 스크립트를 사용하지 않는다면, 테스트 머신에 CATALINA_HOME 환경 변수를 설정하지 말아라. 이 변수가 설정되면, 모든 인스턴스는 톰캣 인스턴스를 구동하기 위해 같은 디렉토리(CATALINA_HOME 변수에 정의된)를 사용하려고 할 것이다. 그러한 결과로, 오직 최초의 인스턴스만 성공적으로 구동되고 나머지 인스턴스들은 포트가 이미 사용되고 있다는 바인드 익셉션 메세지와 함께 구동에 실패할 것이다: "java.net.BindException: Address already in use: JVM_Bind:8080".

로드 밸런서 설정

필자는 웹 리퀘스트를 리다이렉트 시키기 위해 룰 API를 상속받은 두개의 간단한 커스텀 로드 밸런싱 룰을 작성했다.(RoundRobinRule과 RandomRedirect) 이 룰들은 라운드 로빈과 랜덤 리다이렉트와 같은 로드 밸런싱 알고리즘에 의거한다. 여러분들도 가중치 기반, 마지막 접속 시간 등과 같은 다른 요소들을 기반으로 하는 비슷한 커스텀 로드 밸런싱 룰을 작성할 수 있다. 톰캣 로드 밸런서는 파라미터 기반의 로드 밸런싱 룰을 예제로 제공한다. 이것은 HTTP 리퀘스트의 파라미터에 따라 웹 리퀘스트를 다른 URL로 리다이렉트 시킨다.
TC-LB 인스턴스는 클러스터 멤버로 사용하기 않기 때문에, TC-LB의 server.xml의 cluster와 valve 요소는 주석을 제거하지 말아라.

테스팅 설정

세선 영속성 테스팅

세션 영속성 테스팅에서 주 목적은 클러스터 멤버가 웹 리퀘스트 처리 도중 다운됐을 때 세션 데이터가 손실되지 않았다는 것을 검증하는 것이다. sessiondata.jsp 페이지는 세션의 자세한 정보를 보여주기 위해 사용됐다. 이 스크립트는 또한 세션 속성을 추가/변경/제거 하기 위한 HTML 텍스트 필드를 제공한다. HTTP 세션에 몇 가지 속성을 추가한 후에, 필자는 랜덤하게 클러스터 노드를 중지시키고 나머지 사용가능한 클러스터 멤버에서 세션 데이터를 체크했다.

부하 테스팅

부하 테스팅의 목적은 커스텀 로드 밸런싱 알고리즘을 연구하고, 특히 하나 또는 그 이상의 노드가 다운됐을 때 웹 리퀘스트가 얼마나 효율적으로 클러스터의 노드에 분배되는지 알아보는 것이다. JMeter 부하 테스팅 툴이 다수의 동시 접속 웹 유저를 시뮬레이트 하기 위해 사용됐다.
클러스터 설정에서 로드 밸런싱을 테스트하기 위한 절차:
  1. 로드 밸런서와 톰캣 서버의 클러스터 인스턴스들을 구동한다.
  2. 시작 JSP 스크립트를 구동한다. (testLB.jsp).
  3. 랜덤한 간격으로 하나 또는 그 이상의 서버를 중지시켜서 서버 다운을 시뮬레이트한다.
  4. 부하 분배 패턴을 체크한다.
  5. 절차 1부터 4를 100번 반복한다
모든 로그 메세지는 tomcat_cluster.log (tomcat50/webapps/balancer 디렉토리에 위치) 라고 불리는 텍스트 파일에 기록된다. 시퀀스 다이어그램(Figure 2)에서 보여준 모든 웹 객체에 대한 응답 시간이 Log4J 메세지를 사용하여 기록되었다. 경과시간(밀리세컨드) 자료들이 수집되고 테이블 3에 자료로 나타나 있다. 필자는 테스트동안 응답 시간을 수집하는데 Designing Performance Testing Metrics into Distributed J2EE Apps에 기술된 것과 비슷한 방법론을 따랐다.
다음 테이블은 각각 부하 테스팅 (RoundRobinRule을 사용)의 경과시간과 부하 분배율 (RandomRedirectRule을 사용) 보여준다.
Table 3. 부하 테스팅 경과시간
#ScenariotestLB.jsp
(ms)
RoundRobinRule
(ms)
sessiondata.jsp
(ms)
Total
(ms)
13개의 모든 서버 인스턴스가 실행중547612142
22개의 서버 인스턴스가 실행중 (TC02은 중지상태)5553114600
31개의 서버 인스턴스만 실행중
(TC01, TC02 중지상태)
561900111967
주: 모든 경과시간은 100명의 동시접속 유저의 부하를 바탕으로한 평균값이다.
Table 4. 랜덤 LB 정책을 사용했을 때 부하 분배
#ScenarioTC01 (%)TC02 (%)TC03 (%)
13개의 모든 서버 인스턴스가 실행중304624
22개의 서버 인스턴스가 실행중 (TC02은 중지상태)56044
주: 부하 분배율은 100명의 동시접속 유저의 부하를 바탕으로한 값이다.

결론

세션 영속성 테스팅에서, 세션 속성을 추가한 후에 클러스터 노드 중의 하나가 다운되고 세션 속성은 서버 다운때문에 손실되지 않았음을 검증했다. 텍스트 파일에 기록된 세션의 자세한 정보는 세션 속성의 상세값을 연구하기 위해 사용됐다.
부하 테스팅에서 하나 또는 2개의 서버 인스턴스가 중지되고 오직 하나의 톰캣 인스턴스만 실행중일 때, 응답 시간은 3개의 인스턴스가 모두 사용가능 했을 때에 비해 길어졌다. 중지된 인스턴스가 재시작됐을 때, 로드 밸런서는 자동적으로 서버가 다시 리퀘스트를 처리할 수 있도록 사용가능하다는 것을 알아냈고 다음 웹 리퀘스트를 리다이렉트 시켰다. 이것은 응답 시간을 현저하게 향상시켰다.
클러스터 멤버가 사용가능한지 알아보기 위해(ServerUtil 클래스를 사용하여) 필자가 사용한 메카니즘은 가장 빠른 방법은 아니다. 더욱 복잡하고 견고한 fail-over 테크닉들이 실세계의 시나리오에서 사용되어야 할 것이다.
제시된 클러스터 설정의 한계점 중의 하나는 단지 하나의 로드 밸런서만 제공한다는 것이다. 로드 밸런서 역할을 하는 톰캣 인스턴스가 다운된다면 어떤 일이 벌어지나? 어떤 클러스터 멤버에게도 리퀘스트를 포워딩할 방법이 없고, 그러한 결과로 이것을 소위 Single Point of Failure(SPoF)라고 한다. 이 문제에 대한 한가지 해결책은 만약 주 로드 밸런서가 다운된다면 그 역할을 이어받을 대기 로드 밸런서로서 두번째 톰캣 인스턴스를 가지고 있는 것이다. 전형적인 HA(High Availability) 옵션은 SPoF 상황을 방지하기 위해 2개의 로드 밸런서를 가지고 있는 것을 포함한다.
예제 클러스터 설정에서, 모든 톰캣 인스턴스(로드 밸런서를 포함해서)는 단일 컴퓨터에서 실행되도록 설정되었다. 더 좋은 디자인은 로드 밸런서를 클러스터 멤버로부터 분리된 머신에서 실행하는 것이다. 또한 수평 확장 방법론의 이점과 클러스터 성능을 향상시키기 위해 클러스터 노드를 1 머신당 2개로 제한하는 것이다.
HTTP 세션 복제는 J2EE 웹 어플리케이션 서버에서 값비싼 작업이다. 클러스터링된 J2EE 환경에서 세션 관리의 포함은 웹 어플리케이션이 제품 환경에 구현될 때까지 기다리는 것보다 프로젝트의 분석과 디자인 단계에서 고려되어야 한다. 어플리케이션 코드는 클러스터 환경을 염두에 두고 디자인되어야만 한다. 만약 클러스터링 환경을 포함하는 것이 디자인 단계에서 고려되지 않는다면, 클러스터 설정에서 작동하기 위해 코드는 아마도 완전히 재작성될 필요가 있을 수도 있고, 이것은 매우 값비싼 노력이 될 것이다.
만약 웹 어플리케이션이 객체 캐슁 메카니즘에 대한 어떤 종류의 지원이라도 한다면, 클러스터 환경에서의 객체의 캐슁은 어플리케이션 개발의 초기단계부터 고려되어야만 한다. 캐쉬된 데이터를 모든 클러스터 노드에서 동기화된 상태로 가지는 것은 웹 유저에게 정확하고 최신으로 갱신된 비지니스 데이터를 제공하기 위해 핵심적이기 때문에 이것은 매우 중요하다. 또 다른 중요한 고려사항은 클러스터 내의 만료된 세션 데이터를 제거하는 것이다.
J2EE 클러스터가 성공적으로 설정되고 실행되면, 확장성과 고가용성의 이점을 제공하기 위해 그 관리와 유지보수가 매우 중요해질 것이다. 클러스터에 많은 노드를 가지고 있으면, 유지보수는 클러스터가 실행되도록 유지하고 어플리케이션의 변경을 모든 클러스터 노드에 적용하도록 순환해야 한다. 이러한 서비스를 제공하는 한가지 방법은 정기적으로 서버의 사용가능성을 체크하고 클러스터의 노드 중 어떤 것이 다운되면 공지하는 모니터링 서비스를 구현하는 것이다. 이 서비스는 다운된 노드를 감지하고 그것을 액티브 노드 목록에서 제거해서 리퀘스트가 다운된 노드로 가지 않도록 정기적인 간격으로 노드를 체크해야 한다. 이 서비스는 변경이 일어날 때마다 클러스터 내의 모든 서버를 업데이트하고 동기화하는 능력을 포함해야 한다. 웹 어플리케이션에 대한 모든 리퀘스트는 로드 밸런싱 시스템을 통해야 하기 때문에, 시스템은 액티브 세션의 수, 어떤 인스턴스에 연결된 액티브 세션의 수, 응답 시간, 피크 부하 시간, 피크 부하 동안의 세션의 수, 최저 부하 동안의 세션의 수 등을 알 수 있다. 모든 기록 정보는 최적화 성능을 위해 전체 시스템의 세밀한 조정에 사용될 수 있다. 로드 밸런싱 정책과 클러스터 노드의 효율성을 평가하기 위한 기초로서 이러한 결과를 보여주는 리포트가 생성되야만 한다.
현재 클러스터와 로드 밸런서 설정에 필요로 하는 모든 설정은 설정 파일(server.xml과 rules.xml)을 조작함으로써 수동으로 이루어 졌다. 자카르타 그룹이 클러스터링과 로드 밸런싱 설정을 관리하기 위해 필요로 하는 설정의 변경을 수행할 수 있는 웹 기반의 클러스터 관리 GUI 툴을 제공한다면 매우 도움이 될 것이다.

참고 자료

Srini Penchikala는 Flagstar Bank의 정보 시스템 주제 관련 전문가이다.

댓글

이 블로그의 인기 게시물

4,5,6 띠 저항의 색띠를 읽는 법(띠저항 값)

수지에서 인천공항 리무진 버스 (인천공항버스정보)(2022년3월업데이트)

수지에서 김포공항 리무진 버스 ( 2022년 3월 업데이트 )