제4장 JEUS 클러스터링

내용 목차

4.1. 클러스터링 종류
4.2. 노드 클러스터링
4.2.1. 노드 클러스터링 형성
4.2.2. 노드 클러스터링 상태 전이
4.2.3. 노드 클러스터링 동적 노드 추가
4.2.4. 백업 노드
4.3. 노드 클러스터링 설정
4.3.1. 노드 클러스터링 설정
4.3.2. 백업 노드 설정
4.4. 노드 클러스터링 컨트롤

본 장에서는 JEUS의 클러스터링의 구조 및 동작에 관해 전반적으로 설명한다.

4.1. 클러스터링 종류

시스템 과부하와 장애 대책을 위해서 JEUS 여러 노드를 클러스터링으로 묶어서 운영할 수 있다. 이를 JEUS 간의 클러스터링이라고 한다.

JEUS는 여러 가지 방식의 클러스터링 기능을 제공하고 있다. 사용하려는 목적에 따라 어떤 형태의 클러스터링이 필요한지 다를 수 있으므로 사용자의 목적에 맞게 필요한 부분을 적용하도록 해야 한다.

  • 노드 클러스터링

    가장 기본이 되는 클러스터링으로 각 노드들은 서로 1:1로 연결을 형성하고 서로 메시지를 보내어 통신하게 된다. 일정한 주기(기본 15초. 주기는 시스템 프로퍼티로 설정 가능)마다 상대 노드가 살아있는지 Keep-Alive 메시지를 주고받아 상태를 관리하게 된다. 시스템 프로퍼티에 대한 자세한 내용은 JEUS Reference Book”의 “1.2. 서버 시스템 프로퍼티”를 참고한다.

    노드 클러스터링은 JNDI 클러스터링, Security 서버 클러스터링, 세션 클러스터링과 EJB 클러스터링을 위한 기본 요건이다. JNDI 클러스터링과 Security 서버 클러스터링은 JEUS Manager가 클러스터링을 형성할 때 자동으로 형성되므로 별다른 설정은 필요없지만 웹 서버와 세션, EJB 클러스터링은 특별한 설정이 필요하다.

  • JNDI 클러스터링

    Naming 서버들 간의 Binding 객체들을 공유하기 위해 사용된다. 즉, A,B,C 클러스터링 환경에서 A에서 bind한 객체는 B, C에서도 lookup이 가능하고 A가 다운되어도 B, C에서는 여전히 A에서 bind한 객체를 lookup할 수 있다. 자세한 내용은 “제6장 JNDI Naming Server”를 참조한다.

  • Security 도메인 클러스터링

    기본적으로 도메인별 보안 서비스를 적용하기 위해서 도메인 클러스터링을 지원한다. 자세한 내용은 JEUS Security 안내서”의 “제1장 보안 시스템의 소개”를 참조한다.

  • 웹 서버 클러스터링

    웹 서버와 서블릿 엔진으로 구성된다. 시스템의 HTTP 처리의 성능 향상을 위해서 사용한다. 자세한 내용은 JEUS Web Container 안내서”의 “제4장 웹 서버 연결과 클러스터링”을 참조한다.

  • 세션 클러스터링

    서블릿의 세션 데이터의 분산 처리와 EJB Stateful Session Bean의 Failover를 위해서 사용된다. 세션 클러스터링에는 중앙 집중 세션 서버와 분산 세션 서버의 방식이 있다. 자세한 내용은 “제10장 세션 서버”를 참조한다.

  • EJB 클러스터링

    EJB 엔진과 Bena의 백업 및 부하 분산을 위해서 사용한다. 자세한 내용은 JEUS EJB 안내서”의 “제6장 EJB 클러스터링”을 참조한다.

각각의 클러스터링 종류에 대한 자세한 방식은 각 부분을 참조하도록 하고 여기서는 노드 클러스터링의 부하 분산(Load Balancing)과 Failover에 대해서 설명한다.

4.2. 노드 클러스터링

시스템 과부하와 장애 대책을 위해서 JEUS 여러 노드를 클러스터링으로 묶어서 운영할 수 있다. 이를 JEUS 간의 클러스터링이라고 한다.

클러스터링에 속하는 모든 노드의 정보는 각 노드의 JEUSMain.xml 파일에 담겨 있게 된다. 그래서 각 노드는 자신의 JEUSMain.xml 설정을 이용해서 클러스터링 내의 모든 노드를 구별하게 된다.

[그림 4.1] 3개의 노드와 설정 파일(JEUSMain.xml)을 포함한 JEUS 클러스터링

3개의 노드와 설정 파일(JEUSMain.xml)을 포함한 JEUS 클러스터링


위의 그림에서 노드 A, B, C의 JEUSMain.xml 파일 3개는 거의 유사하다. 설정에서 <node> 태그가 100% 동일할 필요는 없으나, 동일하게 사용하는 것을 권장한다. 실제 중요한 것은 클러스터 내의 노드가 모두 JEUSMain.xml에 포함되어 있어야 한다는 것이다. 그리고 타 노드의 정보는 노드의 이름 정도만 포함시켜도 무방하다. 예를 들면 A노드의 JEUSMain.xml에 B노드의 모든 정보를 포함시킬 필요는 없고 단지 B노드의 <node>/<name> 태그까지의 정보만 포함시키면 가능하다.

그러면 각 노드는 자신이 사용할 노드가 셋 중 어떤 것인지 어떻게 알아내는가? 바로 hostname(표준 Java API 를 사용해서)을 얻고 JEUSMain.xml 에서 설정된 노드명을 비교함으로써 결정된다. 노드명이 hostname과 일치하는 노드의 설정을 사용하게 된다.

예를 들어 노드가 호스트 “A”에서 동작을 시작할 경우 노드 “A”의 설정을 사용한다. 다른 2개 노드의 설정 정보는 클러스터링을 형성하는 다른 노드에서 사용한다. 만약 가상 호스트(Virtual Host)를 사용하는 경우에는 hostname과 base port를 가지고 JEUS_HOME\config\vhost.properties에서 실제 호스트 이름을 찾아서 노드명과 비교함으로써 자신의 노드를 찾을 수 있다. 가상 호스트에 대한 설명은 “1.2.1. 가상 노드”를 참조하고 설정에 대해서는 “2.2.2. 가상 노드 설정”을 참조한다.

4.2.1. 노드 클러스터링 형성

JEUS 노드 간에 클러스터를 구성할 때 JEUS는 다음과 같은 방식으로 노드 간에 연결을 구성한다.

  1. 각 JEUS Manager는 설정 파일(JEUSMain.xml)에서 자신의 노드 이외의 노드와 연결을 시도한다.

  2. 만약 노드 하나가 죽은(dead)것으로 확인되면(JEUS Manager 간의 연결이 되지 않았거나 끊어졌을 때) 강제로 클러스터링에서 제외된다. 그래서 “dead” 노드는 클러스터가 형성될 때 무시하고 넘어가게 된다. 자세한 내용은 "노드 클러스터링을 형성한 노드에 장애가 발생할 경우"를 참고한다.

  3. JEUS Manager가 이전에 죽은(dead) 노드와 제외된 노드가 다시 살았는지(alive)를 확인하고, 살았다면 클러스터링에 포함한다.

노드 클러스터링을 형성한 노드에 장애가 발생할 경우

JEUS 클러스터링 상태에서 장애는 OS 레벨 에러나 네트워크 단절 등 다양한 원인으로 발생될 수 있다.

다음 그림에서 노드 B는 에러로 장애가 발생한다.

[그림 4.2] 노드 클러스터링 장애

노드 클러스터링 장애


그림에서 노드 B가 장애가 발생했을 때, 노드 A와 C는 그것을 감지하고 노드 B가 다시 살아나는지 여부를 일정한 주기로 Keep-Alive 메시지를 보내서 계속 확인한다. 이 Keep-Alive check는 기본이 15초마다 수행되고 시스템 프로퍼티(JEUS Reference Book”의 “1.2. 서버 시스템 프로퍼티”)로 설정 가능하다. 만약 노드 B가 살아나면, 노드 A와 C는 Keep-Alive check를 통하여 감지해 낸다. 그리고 클러스터링은 이전의 형태를 복구해서 [그림 4.1]로 되돌아간다.

위와 같이 각 노드는 자신의 위치에서 다른 노드들의 이상 여부를 check해서 클러스터링 정보를 유지한다. 해당 정보는 jeusadmin의 nodelist 명령으로 확인할 수 있다.

4.2.2. 노드 클러스터링 상태 전이

노드 클러스터링의 경우 Target 노드에 대해 다음과 같은 3가지의 상태를 가지고 있다.

다음은 상태 전이에 대한 그림이다.

[그림 4.3] 클러스터링의 상태 전이

클러스터링의 상태 전이
상태설명
INACTIVE

노드 클러스터링의 커넥션 연결이 정상 종료된 상황 또는 초기치의 상태이다.

(예: Target 노드의 정상 다운)

RUNNING

노드 클러스터링의 커넥션 연결이 정상적인 상황이다.

(예: Target 노드의 정상 운영 상태)

FAILED

노드 클러스터링의 커넥션 연결이 비정상 종료된 상황이다.

(예: Target 노드의 비정상 다운. 장애 또는 kill -9 등으로 다운된 상황)


RUNNING 상태에서 INACTIVE 또는 FAILED 상태로 변경이 가능하며, 반대로 INACTIVE 또는 FAILED 상태에서 RUNNING 상태로의 변경도 가능하다. 하지만 INACTIVE 상태에서 FAILED 상태로 또는 FAILED 상태에서 INACTIVE 상태로의 변경은 불가능하다.

INACTIVE, FAILED의 상태일 경우 노드 클러스터링에서 제외되며, 차후 주기적인 모니터링 기능을 통해 재연결이 가능하다.

4.2.3. 노드 클러스터링 동적 노드 추가

일반적인 클러스터링 방법은 각 노드에 클러스터링을 구성하는 노드의 정보를 각 노드가 가지고 있는 것으로 정적 클러스터링 구성이라고 한다.

반면에 JEUS 노드를 동적으로 추가해야 할 경우가 있다. 즉, 별개로 설정된 JEUS 노드가 동작 중인 JEUS 클러스터에 추가될 수 있다. 이를 위해서는 동적으로 추가하고 싶은 노드에만 클러스터링에 포함되는 노드의 정보를 모두 설정하고 실행시키면 각 노드에 동적으로 기동된 노드가 연결을 시도한다.

다음의 그림은 이러한 작업을 보여준다. 그림(2번째 지점)에서 보듯 새 노드에서 JEUS를 실행하면, 클러스터링의 다른 노드에서 새 노드의 존재와 설정에 대해서 알지 못하더라도 “JOIN” 시도가 진행된다.

[그림 4.4] JEUS 클러스터에 새로운 JEUS 노드(D)의 동적 추가

JEUS 클러스터에 새로운 JEUS 노드(D)의 동적 추가


그 결과 D는 A, B, C 노드에게 접속을 시도해서 A, B, C에게 자신의 존재를 알린다. 결국 A, B, C, D는 모두 서로를 체크하면서 클러스터링을 이룬다.

참고

동적으로 D 노드가 추가 되더라도 A ,B, C 노드의 JEUSMain.xml에 D 노드를 추가해 주지 않는다. 따라서 A, B, C, D 노드를 모두 재시작할 때 A, B, C, D 노드가 정적으로 클러스터링을 형성하지 않는다.

4.2.4. 백업 노드

노드 클러스터링은 클러스터링에 참여하는 모든 노드가 동등한 입장으로 부하 분산을 수행하는 것과 달리 주 노드와 백업 노드 방식은 2개의 노드가 있을 때 다른 한 노드를 Failover를 위한 백업 노드로 사용하고자 할 때 이용할 수 있다.

백업 노드는 자신이 백업해야 하는 노드(주 노드)가 다운이 되었을 경우에만 그 노드를 대신하여 Failover 작업을 수행한다. 주 노드가 종료(Down)되었을 때 백업 노드는 자동으로 기동되어 다운된 노드의 설정 데이터를 읽고 그 설정에 따라 엔진 컨테이너를 부팅하여 서비스가 계속 유지되도록 한다. 백업 노드는 또한 서비스 수행하면서 주 노드가 살아 났는지 일정한 주기로 확인을 하고 주 노드가 살아나면 백업 노드는 주 노드의 Failover 작업 수행 전의 상태로 돌아간다.

백업 노드는 주 노드가 다운되었을 경우에만 주 노드의 서비스를 대신해주기 때문에 주 노드가 정상 동작하는 경우에는 백업 노드는 아무 일도 수행하지 않는다. 따라서 백업 노드가 있는 머신은 평소에는 다른 용도로 사용되다가 주 노드가 정상적이지 않을 경우에만 백업을 수행하고자 하는 경우에 유용하게 사용될 수 있다.

참고

주 노드의 종료(Down)라 함은 주 노드의 비정상종료(FAILED) 상태를 의미하며, 기본적으로 주 노드가 정상종료(INACTIVE)된 경우 백업 노드는 아무 동작을 하지 않는다. 즉, 주 노드의 상태가 RUNNING -> FAILED로 변경되는 상황에서 백업 노드는 주 노드를 대신하여 서비스를 수행한다.

단, 주 노드가 백업 노드를 기동(Booting)하도록 하는 옵션을 주고 정상종료(INACTIVE)한 경우 백업 노드는 서비스를 수행한다. 즉, RUNNING -> INACTIVE 로 변경되는 상황이더라도 백업 노드는 주 노드를 대신하여 서비스를 수행한다. 이 옵션에 대한 자세한 설명은 JEUS Reference Book”의 “4.2.3. 공통 명령어”를 참조한다.

백업 노드에 대한 설정에서 주의할 점은 A의 백업 노드가 B이면 A의 노드 설정에 B를 자신의 백업노드로 설정하는 것이 아니라 B노드에 B가 백업할 대상의 노드가 A임을 설정한다는 것이다. 좀 더 자세한 설정은 “4.3.2. 백업 노드 설정”을 참조한다.

4.3. 노드 클러스터링 설정

4.3.1. 노드 클러스터링 설정

JEUS 클러스터링은 서로 다른 노드 간의 클러스터링이므로 네트워크 관련 설정이 정확하게 이뤄져야 하고 하나의 노드는 다른 노드에 대해서 정확하게 알아야 하므로 설정할 때 다음의 3가지를 주의한다.

  • 각 머신의 호스트 파일에 클러스터링되는 머신의 hostname과 IP 주소를 정확히 매핑해야 한다.

    hostname과 IP 주소는 UNIX의 경우 /etc/hosts 파일에서 매핑하고, Windows의 경우에는 %SystemRoot%\system32\drivers\etc\hosts 파일에서 매핑한다.

  • 가상 노드를 사용하는 노드가 있다면 클러스터링에 참여하는 모든 머신의 vhost.properties에 가상 노드를 사용하는 노드의 실제 hostname을 설정해 놓아야 한다.

    가상 노드를 사용하도록 설정(jeus.vhost.enabled 값을 true로 설정)하며, 각 머신의 vhost.properties에 모든 머신의 정보를 입력(즉, 각 가상 노드의 이름과 BASEPORT의 값을 입력)한다. 만약, 가상 노드를 사용하지 않는다면, 모든 머신이 가상 노드를 사용하지 않도록 설정(jeus.vhost.enabled값을 false로 설정)하며, 각 머신의 JEUS_BASEPORT를 동일하게 설정한다.

  • JEUS의 관리자 ID와 패스워드를 모든 노드에 동일하게 적용한다.

이제 JEUSMain.xml에서 어떻게 설정되는지 예제를 통해 설명한다. WebAdmin을 이용하면 쉽게 설정할 수 있으나 본 절에서는 직접 XML에 설정하는 방법을 설명한다.

클러스터링을 만들기 위해서는 클러스터링에 참여하는 각 노드의 JEUSMain.xml을 수정해야 한다. 각 JEUSMain.xml 파일에는 반드시 클러스터링에 참여하는 노드들의 <node>에 설정되어야 한다.

[예 4.1] 노드 클러스터링의 설정 1 : <<JEUSMain.xml>>

<jeus-system>
    <node>
        <name>
            A
        </name>
        . . .     <!—노드의 다른 설정부분 -->
    </node>
    <node>
        <name>
            B
        </name>
        . . .     <!—노드의 다른 설정부분 -->
    
    </node>
    <node>
        <name>
            C
        </name>
        . . .     <!—노드의 다른 설정부분 -->
    </node>
    . . .   <!—Manage의 다른 설정부분, -->
</jeus-system>

위의 예에서 3개의 노드 A, B, C는 클러스터링의 각 JEUSMain.xml 파일에서 설정되어 있다. 위 예제처럼 클러스터링에 참여하는 모든 노드의 설정을 해도 되지만 다음의 예제처럼 각 노드에 포함되는 JEUSMain.xml에 자기 노드에 대한 자세한 설정과 클러스터링에 참여하는 <node>/<name> 태그만 설정해도 무방하다.

[예 4.2] 노드 클러스터링의 설정 2 : << JEUSMain.xml>>

<jeus-system>
    <node>
        <name>
            A
        </name>
        . . .     <!—노드의 다른 설정부분 -->
    </node>
    <node>
        <name>
            B
        </name>    
    </node>
    <node>
        <name>
            C
        </name>
    </node>
    . . .   <!—Manager의 다른 설정부분, -->
</jeus-system>


위의 클러스터링 예에 동적으로 D 노드를 추가하는 작업은 D 노드의 JEUSMain.xml에 D 노드의 설정과 A, B, C 노드의 이름을 추가한다. 그리고 D 노드를 기동(boot)하면 현재 동작 중인 클러스터에(A,B,C 노드) 동적으로 새로운 노드(D 노드)가 추가된다.


4.3.2. 백업 노드 설정

위에서 설명 했듯이 <backup-node>를 주 노드가 아닌 백업 노드에 설정해야 함을 주의해야 한다. 예를 들어 A의 노드가 주 노드이고 B 노드가 백업 노드이면 B 노드의 JEUSMain.xml에 <backup-node>로 A 노드를 추가하고 A 노드의 JEUSMain.xml에는 B에 대한 설정을 하지 않는다.

또한 주 노드, 백업 노드의 기능을 사용하기 위해서는 서로 간의 노드 클러스터링 설정이 먼저 되어 있어야 한다.

[예 4.3] 백업 노드 설정 1 : << JEUSMain.xml>>

<jeus-system>
    <node>
        <name>A</name>
        . . .     <!—노드의 다른 설정부분 -->
    </node>
    . . .   <!—Manager의 다른 설정부분, -->
</jeus-system>


[예 4.4] 백업 노드 설정 2 : << JEUSMain.xml>>

<jeus-system>
     <node>
        <name>B</name>
        <backup-node>A</backup-node>

        . . .     <!—노드의 다른 설정부분 -->
    </node>

    . . .   <!—Manager의 다른 설정부분, -->
</jeus-system>


4.4. 노드 클러스터링 컨트롤

클러스터는 다음의 과정으로 컨트롤할 수 있다.

  1. 클러스터를 시작하기 위해서는 먼저 jeus 명령으로 각 JEUS들을 시작한다.

  2. jeusadmin 콘솔 툴 또는 WebAdmin을 열어서 각각의 JEUS Manager에 boot 명령을 내린다. 기동 순서는 상관 없다.

  3. 클러스터링을 종료하려면, 클러스터링의 각 노드에 down 명령을 실행하여 shutdown시킨다. 완전히 클러스터링을 종료하려면 jeusexit 명령을 사용한다.

참고

콘솔 툴9jeusadmin0에 관한 자세한 설명은 JEUS Reference Book”의 “4.2.3. 공통 명령어”를 참조한다.