메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

한빛랩스 - 지식에 가능성을 머지하다 / 강의 콘텐츠 무료로 수강하시고 피드백을 남겨주세요. ▶︎

IT/모바일

Tomcat 클러스터링

한빛미디어

|

2002-08-20

|

by HANBIT

13,528

저자: 시암 쿠마르 도다불라(Shyam Kumar Doddavula)

본 기사는 클러스터링이 웹 애플리케이션에 어떤 이익을 줄 것인지, 자바스페이스(JavaSpaces) 기술을 사용한 고도의 확장성, 부하분산(load-balancing), 고가용성(availability)을 제공하는 자카르타 톰캣(Jakarta Tomcat) 서블릿 엔진을 위해 개발한 클러스터링 솔루션에 대해 기술한 글이다.

소개

웹 기반 애플리케이션 사용이 증가함에 따라 성공에 결정적인 영향을 주는 요인으로 확장성과 가용성이 대두되고 있다. 웹 애플리케이션을 수용하는 서버에 클러스터링 솔루션을 구축하는 것은 간단하면서도 비용을 절감시켜주는 솔루션이라 할 수 있다.

자바스페이스 기술은 클러스터링 솔루션을 설계하는데 사용 될 수 있는 분산 공유 메모리 모델을 제공한다. 원격 절차 호출(RPC: remote procedure calling)을 가능하게 하거나 메시지 교환을 반복적으로 실행하는 전형적인 분산시스템 기법과는 달리, 이 기술을 사용하는 솔루션은 오브젝트를 전달하는 능력을 수행한다. 이들 오브젝트는 일반적인 원격시스템에서 작업을 수행하는데 필요한 모든 정보(심지어 소스코드까지)를 연상, 공유, 분산 메모리를 사용하여 운반한다. 자바스페이스는 오브젝트를 스페이스에 추가하고, 오브젝트 복사본을 읽어오고, 스페이스로부터 오브젝트를 가져오는 간단한 쓰기, 읽기, 가져오기 연산 집합을 제공한다.


[그림 1] 자바스페이스를 사용한 분산시스템(Sun Microsystems승인 하에 사용)

자바스페이스는 지니(Jini) 기술 서비스의 핵심이다. 지니 프로그래밍 모델은 리스 모델(leasing model)과 동적 서비스 디스커버리(dynamic service discovery)를 통해 자체적으로 구성되는(self-configuring) 능동적인 분산시스템을 만드는데 필요한 하부구조를 제공한다. 이 기술에 대해 보다 많은 정보는 아래 관련자료를 참고하면 된다.

지니 프로그래밍 모델과 결합된 자바스페이스 기술은 높은 시공완화(spatial and temporal decoupling)를 제공하기 때문에 고도로 확장가능하며, 장애 허용적이고(fault-tolerant), 동적으로 구성할 수 있는 분산시스템 설계를 가능하게 해준다. 본 기사에서는 이와 같은 기술들을 사용하여 서블릿 API 구축에서 각광 받는 오픈 소스인 톰캣 서블릿 엔진(Catalina 4.x)을 위한 간단한 클러스터링 솔루션에 대해 살펴보고자 한다.

왜 클러스터링인가?

클러스터링 솔루션이 일반적으로 제공하는 것은 다음과 같은 것들이다.
  • 확장성(Scalability)
  • 고가용성(High Availability)
  • 부하분산(Load Balancing)
확장성

여기서 핵심질문은 "하나의 요청을 처리하는데 T라는 시간이 소요된다면 N개의 동시 요청을 처리하는 데는 얼마의 시간이 걸릴까?"하는 것이다. 목표는 부하가 증가됨에 따라 컴퓨팅 자원을 증가시켜 가능한 한 T에 가깝게 시간을 가져가는 것이다. 이상적인 솔루션은 수직적(서버의 컴퓨팅 자원을 증가시키는 것) 및 수평적(서버 수를 늘리는 것) 확장을 모두 지원해야 하며 확장은 선형적이어야 한다.

고가용성

여기서의 목표는 오류극복 기능을 제공하는 것이다. 클러스터의 한 서버가 작동이 불가능하게 되면 클러스터 내의 다른 서버가 작업을 대신 수행해야 하며 최종 사용자에게는 가능한 한 투명하게 진행되어야 한다.

서블릿 엔진의 경우 클러스터링 솔루션에 의해 제공되는 전형적인 오류극복 기능이 있으며 이는 다음과 같은 두 단계로 이루어 진다.
  • 요청단계 오류극복(Request-level Failover)
  • 세션단계 오류극복(Session-level Failover)
요청단계 오류극복 클러스터 내 하나의 서버가 작동할 수 없게 되면 모든 후속 요청은 클러스터 내의 정상적인 서버에 재전달 되어야 한다. 일반적인 클러스터링 솔루션에서는 서버의 상태를 지속적으로 추적하고 응답이 없는 서버에는 요청을 전송하지 않는 심장박동 메커니즘(heartbeat mechanism)을 이용하는 것을 포함한다.

세션단계 오류극복 HTTP 클라이언트는 서버에서 관리되는 세션을 가질 수 있다. 따라서 세션단계 오류극복이라는 것은 클러스터의 서버가 작동 할 수 없게 되면 클러스터 내의 다른 서버들이 오류발생 서버가 관리하던 세션의 연속성 상실을 최소화하며 연계하여 작동할 수 있어야 한다는 것이다. 일반적인 클러스터링 솔루션에서는 세션 정보를 클러스터 간(적어도 클러스터 내의 다른 한 서버)에 복제하는 것으로 구현된다.

부하분산

부하분산의 목표는 솔루션이 최종사용자에게 최대한의 응답시간을 제공하기 위해 클러스터 서버 간에 부하를 나눠주어야 한다는데 있다.

일반적인 클러스터링 솔루션에서는 간단한 라운드 로빈 알고리즘(round robin algorithm)이나 서버상의 부하와 가용자원을 지속적으로 추적하여 요청을 분산하는 복잡한 알고리즘 같은 부하분산 알고리즘을 사용하여 구현된다.

제안 솔루션

일반적인 클러스터링 솔루션은 분산 시스템 솔루션 구축하기 위해 클라이언트-서버 패러다임을 사용하는데 확장성에 제한이 있다.

여기서 사용될 스페이스 패러다임에서는 클러스터링이 하나의 서버에서 다른 서버로 오브젝트 이동을 통해서 이뤄지는데 이 오브젝트는 실행되는 현 상태와 바이트코드, 필요하다면 연상, 분산, 공유 메모리를 포함하는 다른 모든 것을 전달한다.

자카르타 톰캣 서블릿 엔진이 어떻게 작동하는지 살펴보자. 이것은 [그림 2]와 같이 요청을 접수하고 수행하기 위해 커넥터(connector)와 프로세서(processor)를 사용한다.


[그림 2] 독립 톰캣 서블릿 엔진의 아키텍처

커넥터는 다른 소스로부터의 요청에서 접수 상세를 추출하며, 프로세서는 요청 수행 상세를 추출한다.

아래 [그림 3]은 제안 클러스터링 솔루션의 아키텍처를 보여준다.


[그림 3] 클러스터링 톰캣 서블릿 엔진의 아키텍처

클러스터 서버 커넥터(Cluster Server Connector)는 클라이언트의 요청을 접수하고 클러스터 서버 프로세서(Cluster Server Processor)는 RequstEntry 오브젝트로 요청을 캡슐화(encapsulate) 하고 자바스페이스에 오브젝트를 기록한다. 클러스터 워커 커넥터(Cluster Worker Connector)는 자바스페이스로부터 이 요청들을 가져오고 클러스터 워커 프로세서(Cluster Worker Processor)는 요청을 수행한다.

이 클러스터 서버와 클러스터 워커들은 복수의 인스턴스로 존재할 수 있으며 여러 대의 기계에 분산될 수도 있다.

RequestEntry는 다음과 같이 정의된다.
public class RequestEntry extends 
      net.jini.entry.AbstractEntry {
  private static int ID = 0;
  public RequestEntry(){
    id = String.valueOf(ID++);
  }
  public String id;
  public RemoteSocketInputStream input;
  public RemoteOutputStream output;
}
id 필드는 요청을 식별한다. 입력 필드인 RemoteSocketInputStream 오브젝트형은 원격 기계상의 소켓의 입력 스트림 접속을 제공하고 출력 필드 오브젝트인 RemoteOutputStream은 원격 출력 스트림 접속을 제공한다.

하나의 요청이 접수되었을 때, 소켓의 입출력 스트림은 원격 기계상에서 접속할 수 있는 원격 스트림으로 감싸진다. 요청등록이 이 원격 스트림으로 생성되고 아래의 클러스터 서버 프로세서 코드를 통해 자바스페이스에 기록된다.
...

/**
* 이 프로세서에 할당된 소켓에 들어오는 HTTP 요청을 처리한다. 
* 수행 중 발생한 어떤 예외도 적절하게 흡수, 처리되어야 한다.
* 
* @param socket 클라이언트와 접속하는 소켓
*/


private void process(Socket socket) {
  RemoteSocketInputStream input = null;
  RemoteOutputStream output = null;
  try{
// TC 클래스 로더의 쓰레딩 문제로 인해 동기화 되어야 한다.
    synchronized(this.getClass()){
      input = new RemoteSocketInputStreamImpl(socket, connector.getPort());
      output = new RemoteOutputStreamImpl(socket.getOutputStream());
    }
    log("socket address = " + input.getSocketAddress() + 
    ", port " + input.getServerPort());
    RequestEntry entry = new RequestEntry();
    entry.input = input;
    entry.output = output;
    requestGenerator.write(entry);
  }catch(Exception ex){
  log("parse.request", ex);
  }
}

...
클러스터 워커 커넥터와 프로세서는 아래 코드에서처럼 이들 엔트리를 가져오고 요청을 수행한다.
...
public void run() {
// 셧다운 신호를 받을 때까지 요청을 수행한다
  while (!stopped) {
    log("waiting for entry in JavaSpace...");
    RequestEntry requestEntry = null;
    try{
      synchronized(this){
      ...
      requestEntry = (RequestEntry)requestReader.take();
      ...
      }
    }catch(Exception ex){
      log("internal error while getting request entry from JavaSpace", ex);
    }
    log("got an entry " + requestEntry);
// 요청을 수행한다
    if (requestEntry != null)
      process(requestEntry);
  }
  ...
}
...
제안 솔루션이 제공하는 것들은?

이 솔루션은 부하가 증가함에 따라 클러스터 워커의 수를 증가시킬 수 있다. 또한 이들 클러스터 워커는 여러 대의 기계에 걸쳐 분산될 수 있으므로 고도의 확장성을 제공한다. 이 외에도 여러 대의 기계에서 동작하는 복수의 자바스페이스 서비스 인스턴스가 존재할 수 있고, 집단을 구성하며, 클러스터 서버가 그 중 하나에 기록을 결정할 수 있기 때문에 네트워크 트래픽을 관리를 할 수 있도록 유지한다.

클러스터 서버와 워커는 구현된 자바스페이스 서비스들을 찾기 위해 지니 서비스 디스커버리 메커니즘을 사용하므로 그들의 위치는 하드코딩될 필요가 없다. 따라서 이 솔루션은 동적으로 설정할 수 있다. 지니 리스 모델을 사용하므로 전체 시스템을 셧다운할 필요 없이 추가적인 자원을 첨부할 수 있다. 마찬가지로 현재 자원도 더 이상 지니 라이센스를 갱신하지 않고 현재 라이센스가 만료된 후에 우아하게 제거할 수도 있다.

클러스터 내의 여러 서버에 분산된 요청은 밀어내기식이 아닌 끌어오기식이므로 동작하지 않는 서버에 요청이 전달되는 일은 전혀 없기 때문에 요청단계 오류극복이 제공되는 것이다.

이 솔루션에서 세션정보는 자바스페이스에 있고 필요할 때마다 HHTP 클라이언트가 제공하는 세션 ID를 이용하여 나중에 검색된다. 따라서 이것은 애초에 세션정보를 생성했던 서버가 더 이상 동작하지 않을 때에도 클러스터 내의 다른 서버들은 계속 세션을 가지고 있기 때문에 세션단계 오류극복을 제공하고 있는 것이다. 왜냐하면 우리는 지니 리스 모델을 사용하고 있으므로 자바스페이스에 등록된 세션을 세션종료기간 후에 만료되도록 설정할 수 있고 만료된 세션 정보를 제거하는 도구를 제공한다.
한빛네트워크 기사
톰캣 사용하기 IV - 자바 애플리케이션에 톰캣 임베딩하기
톰캣 사용하기 III - 톰캣 설치와 설정
톰캣 사용하기 II - 톰캣에 웹 애플리케이션 배치하기
톰캣 사용하기 I - 자바 웹 애플리케이션

오라일리 기사
Using SOAP with Tomcat
Using Tomcat 4 Security Realms


부하분산은 끌어오기 기반이기 때문에 여유 자원이 많은 서버가 더 많은 작업을 끌어오는 식으로 부하분산이 자동적으로 이루어진다.

이 설계는 세션 정보 관리 책임을 자바스페이스에 전가하고, 자바스페이스 서비스 구현은 지속적인 형태와 트랜잭션 형태로 제공되기 때문에 필요하다면 보다 쉽게 지속적인 세션을 제공하는 셈이 된다.

현재 우리는 요청을 담아두는 가방 형태로 스페이스를 사용하고 있으나 Build and use distributed data structures in your JavaSpace에서 기술한 대로 최소한의 수정을 통해 채널형태로 만드는 것도 가능하다. 마찬가지로 요청을 필터하는 필터링 서비스 구현도 할 수 있을 뿐만 아니라 서비스품질(QoS) 기능을 제공하도록 우선권을 부여하는 식의 구현도 가능하다.

제안 솔루션의 한계

클러스터 서버가 하나 이상 존재하는 것이 가능하고 모두 동작하게 하는 데에는 별 차이가 없으나 HTTP 클라이언트는 전형적으로 웹 자원에 접속하는데 URL을 사용하므로 클라이언트는 클러스터를 (서버 유연성 향상을 위해) 하나의 IP 주소를 가진 기계로 볼 수 있도록 해야 한다. 따라서 하나의 클러스터 서버가 필요하다. 하지만 이것이 단일 오류 발생지점(single point of failure)이 될 수 있으므로 이 한계는 하드웨어 부하 분산기를 이용하여 극복될 수 있고(그렇다고 하더라도 바로 이 부하 분사기 자체가 단일 오류 발생지점이 될 수도 있다), 이런 경우에 이 솔루션은 웹 서버 프록시(아브라함 캉(Abraham Kang)이 쓴 J2EE Clustering에 대한 기사) 형태로 사용되거나 하나 이상의 기계가 단일 도메인명을 지원하는 기술을 사용할 수 있다. 그밖에 다른 기술은 "ONE-IP: Techniques for Hosting a Service on a Cluster of Machines"에서 찾아볼 수 있다.

결론

이 솔루션은 다른 소프트웨어 솔루션들과 비교할 때 고도의 확장성, 고가용성, 우수한 부하분산 기능을 제공한다. 동적 자가 설정 기능을 제공하므로 유지보수 노력을 절감할 수 있으며 품질서비스(QoS) 기능 구현이라는 유망성도 보유하고 있다.

이 솔루션과 관련된 소스코드 다운받기

관련자료
시암 쿠마르 도다불라(Shyam Kumar Doddavula)Infosys Technologies의 연구개발부서인 SETLabs에서 기술전문가로 근무 중이다.
TAG :
댓글 입력
자료실

최근 본 상품0