제1장 소개

내용 목차

1.1. 구성 요소
1.1.1. Master Server(Master)
1.1.2. Managed Server(MS)
1.2. 클래스 로더의 구조
1.3. 서버 디렉터리 구조
1.4. Launcher

본 장에서는 JEUS 서버의 구성 요소 및 그 구성 요소가 제공하는 서비스에 대해서 설명한다.

JEUS 서버는 여러 개의 서버를 같은 도메인(Domain)으로 묶어 Master Server를 통해 중앙에서 관리할 수 있다.

다음은 JEUS의 주요 구성요소이다.


Master Server(MASTER)는 도메인을 관리하는 서버이다. 도메인에서 오직 하나만 존재한다. MASTER의 역할은 도메인 설정을 관리하고, 도메인에서 서비스되는 애플리케이션을 관리 및 제어한다. 또한 도메인에 속하는 MS를 관리한다.

다음은 MASTER에서만 사용할 수 있는 주요 서비스이다. 도메인 단위로 관리되어야 하는 서비스들이기 때문에 MASTER에서만 실행된다. 사용자가 아래의 서비스들을 사용하기 위해서는 MASTER와 연결된 콘솔 툴(jeusadmin)이나 WebAdmin을 이용해야 한다.

Managed Server(MS)는 실제 애플리케이션을 서비스하기 위한 엔진들과 여러 서비스들을 관장하는 서버 인스턴스를 의미한다. MS는 도메인에 여러 개 존재할 수 있다. MS의 주요 역할은 사용자가 deploy하는 애플리케이션을 서비스하고, 애플리케이션이 필요로 하는 리소스나 서비스를 제공하는 것이다.

다음은 MS의 주요 서비스에 대한 설명이다.

엔진(Engine) 서비스

엔진은 Jakarta EE에서 정의한 EJB 컨테이너, 웹 컨테이너와 매핑되는 개념으로 사용자가 deploy한 컴포넌트를 관리하고 서비스하는 역할을 한다. 엔진은 서버에 포함되는 서비스이며, 사용자가 설정하지 않아도 서버가 부팅할 때 항상 기본 설정으로 실행된다.

서버가 운영 중에 WebAdmin이나 콘솔 툴을 통해 엔진 설정을 변경할 수 있다. 각 엔진에서 제공하는 기본 설정과 동적 변경 가능한 설정에 대해서는 각 엔진의 매뉴얼을 참고한다.

서버에서 제공하는 서비스 엔진은 다음과 같이 3가지 종류가 있다.

엔진설명
EJB 엔진EJB 컴포넌트를 관리하고 실행하는 EJB 컨테이너 역할을 한다. 이에 대한 자세한 사항은 "JEUS EJB 안내서"를 참고한다.

웹 엔진

(또는 서블릿 엔진)

웹 컨테이너라고 할 수 있으며, 웹 클라이언트 또는 웹 서버로부터 요청을 받아서 사용자가 deploy한 Servlet(또는 JSP, JSF)을 통해 동적인 웹 컨텐츠를 생성한다. 이에 대한 자세한 사항은 "JEUS Web Engine 안내서"를 참고한다.
JMS 엔진Jakarta Messaging(JMS)을 제공한다. 이에 대한 자세한 사항은 "JEUS MQ 안내서"를 참고한다.

참고

JEUS 6까지는 엔진 컨테이너에 엔진 설정이 없으면 엔진이 실행되지 않아서 애플리케이션이 서비스될 수 없었다. 웹 엔진을 설정하지 않은 경우에 웹 애플리케이션을 서비스하려면 엔진을 추가하고 JEUS를 재기동해야만 했다. 하지만 JEUS 7부터는 MS를 부팅하면 기본 설정으로 엔진이 실행되어 있는 상태이기 때문에 사용자가 설정하지 않았다고 하더라도 어떤 타입의 애플리케이션이든 deploy하여 서비스 가능하다.

Managed Server의 INDEPENDENT 상태

INDEPENDENT 모드는 MS가 MASTER의 관리 없이 부팅되어 운영되고 있는 모드를 의미한다. 즉, 부팅할 때 MASTER의 URL 정보가 없거나 MASTER가 장애상황인 경우에 발생한다.

MS를 시작시킬 때는 항상 MASTER의 URL 정보를 옵션으로 주어야 한다. Launcher는 서버를 실행할 때 설정한 URL 정보로 MASTER의 URL을 알 수 있기 때문에 이 정보가 없는 경우에는 MASTER로부터 설정을 받아올 수가 없다.

JEUS 8 Fix#1부터 GIT URL을 옵션으로 줄 수 있다. MASTER URL과 GIT URL을 둘 다 줬을 때는 MASTER로부터 설정을 받는 것이 우선시 되지만, MASTER로부터 설정을 받을 수 없는 환경이라면 GIT URL에 있는 설정을 받아온다. MASTER URL과 GIT URL을 주지 않은 경우 부팅하려고 하는 서버의 머신에 캐시되어 있는 설정 파일들이 있다면 서버는 해당 설정 파일을 기반으로 하여 INDEPENDENT 상태로 기동될 것이다. 하지만 서버의 머신에 설정 파일이 존재하지 않는다면 서버는 부팅될 수 없다.

서버의 머신에 설정 파일이 존재한다고 하더라도 이전에 사용하던 파일이기 때문에 Master와 동기화가 맞지 않을 가능성이 높다. 따라서 항상 서버를 부팅할 때는 Master의 URL을 주어야 한다.

MASTER URL을 주지 않아도 되는 경우는 Master와 MS가 같은 머신에 존재하여 도메인 설정 파일을 전송받지 않아도 되는 경우 혹은 GIT URL을 준 경우 밖에 없다. MASTER가 장애상황이 아닌데 URL을 주지 않은 경우에는 서버는 INDEPENDENT 상태라고 인식하겠지만, MS에 그룹 관리 서비스가 시작되고 난 후에는 MASTER와 통신이 되어 다시 DEPENDENT 모드로 복구될 것이다.

INDEPENDENT 상태는 URL을 주지 않은 상황보다 MASTER가 장애상황인 경우에 많이 발생할 것이다. MS를 기동할 때 MASTER가 장애상황이었다면 MS의 Launcher는 설정을 받아오는 작업도 실패할 것이다. MASTER가 failback되어 INDEPENDENT 상태로 부팅된 MS가 DEPENDENT 모드로 복구되면 MASTER로부터 설정 동기화를 하고 Deploy에 실패한 애플리케이션을 다시 deploy한다.

참고

MASTER가 복구되어 설정 동기화를 한다고 하더라도, 동적으로 반영되지 않는 설정이 변경된 경우나 이미 deploy되어 서비스되고 있는 애플리케이션이 변경되었다면 MS를 재기동해야 한다.

다음은 MS가 INDEPENDENT 상태로 부팅했을 때의 로그이다.

JEUS_HOME/bin$ ./startManagedServer -domain domain1 -server server1 -u admin -p admin -masterurl localhost:9736
***************************************************************
- JEUS Home         : /home/admin/JEUS21/
- Java Vendor       : Sun
- Added Java Option :
***************************************************************
=============== JEUS LICENSE INFORMATION ================
=== VERSION : JEUS 21 (21.0.0.0-b417)
=== EDITION: Enterprise (Trial License)
=== NOTICE: This license restricts the number of allowed clients.
=== Max. Number of Clients: 5
==========================================================
[2022.07.13 16:12:50][0] [launcher-1] [Launcher-0052] Receiving the configuration failed. Attempting to start as INDEPENDENT.
<<__Exception__>>
java.io.IOException: Connection failed. host:localhost, port:9736, virtual id:FileTransfer
 at jeus.net.SocketProxy.getConnection(SocketProxy.java:69)
 at jeus.net.SocketProxy.getConnection(SocketProxy.java:25)
 at jeus.server.filetransfer.ConfigurationSynchronizer.connect(ConfigurationSynchronizer.java:116)
 at jeus.server.filetransfer.ConfigurationSynchronizer.connect(ConfigurationSynchronizer.java:99)
 at jeus.server.filetransfer.ConfigurationSynchronizer.checkConnection(ConfigurationSynchronizer.java:141)
 at jeus.server.filetransfer.ConfigurationSynchronizer.downloadConfigFileFromMasterServer(ConfigurationSynchronizer.java:181)
 at jeus.launcher.ManagedServerLauncher.receiveConfigurationFromMasterServer(ManagedServerLauncher.java:245)
 at jeus.launcher.ManagedServerLauncher.updateXmls(ManagedServerLauncher.java:133)
 at jeus.launcher.ManagedServerLauncher.pullLatestDomainType(ManagedServerLauncher.java:67)
 at jeus.launcher.ManagedServerLauncher.initDescriptor(ManagedServerLauncher.java:53)
 at jeus.launcher.Launcher.start(Launcher.java:146)
 at jeus.launcher.ManagedServerLauncher.start(ManagedServerLauncher.java:73)
 at jeus.launcher.ManagedServerLauncher.main(ManagedServerLauncher.java:45)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at jeus.server.Bootstrapper.callMainMethod(Bootstrapper.java:576)
 at jeus.server.Bootstrapper.callMain(Bootstrapper.java:583)
 at jeus.server.Bootstrapper.main(Bootstrapper.java:151)
 at jeus.server.ManagedServerLauncherBootstrapper.main(ManagedServerLauncherBootstrapper.java:10)
<<__Exception__>>
[2022.07.13 16:12:50][1] [launcher-1] [Config-0157] SecurityDomainsConfigServiceProvider is jeus.service.descriptor.SecurityDomainsDescriptorFile.

...
[2022.07.13 16:12:53][0] [server1-1] [SERVER-0249] Successfully started the server INDEPENDENTLY
[2022.07.13 16:12:53][2] [server1-1] [SERVER-0248] The JEUS server is RUNNING.
[2022.07.13 16:12:53][2] [server1-1] [SERVER-0401] The elapsed time to start: 4079ms.
[2022.07.13 16:12:53][2] [launcher-21] [Launcher-0034] The server[server1] initialization completed successfully[pid : 15332].
[2022.07.13 16:12:53][0] [launcher-1] [Launcher-0040] Successfully started the server. The server state is now RUNNING.
JEUS_HOME/bin$ 

그 후에 MASTER가 정상상황이 되었다면 MS는 다시 설정을 동기화하고, deploy에 실패한 애플리케이션이 있었다면 다시 deploy를 수행할 것이다.

[2022.07.13 16:23:20][2] [server1-55] [Domain-0101] JEUS Master Server recovered. server1 is communicating with the JEUS Master server.
[2022.07.13 16:23:20][2] [server1-55] [SERVER-0201] Successfully connected to the JEUS Master Server(192.168.14.63:9736).
[2022.07.13 16:23:20][2] [server1-55] [SERVER-0308] Resynchronized the configuration with JEUS Master Server.

본 절에서는 JEUS에서 지원하는 Isolated Class Loader에 대해서 설명한다.

JEUS는 애플리케이션 간에 클래스가 중복되어 발생하는 문제를 방지하기 위해 애플리케이션마다 서로 다른 클래스 로더(Class Loader)를 사용한다. 이를 Isolated Class Loader(이하 Isolated)라고 하는데, Jakarta EE 표준은 이 방식을 기본으로 사용할 것을 권장하고 있으며 JEUS도 그 권고를 따르고 있다.

다음은 Isolated의 계층 구조이다.


이 구조에서는 각 애플리케이션의 웹 모듈의 클래스 로더가 해당 애플리케이션의 EJB 클래스 로더의 하위에 존재한다. 그리고 한 애플리케이션의 클래스 로더는 다른 애플리케이션의 클래스 로더에 클래스를 요청하지 않는다. Jakarta EE 표준은 애플리케이션이 다른 애플리케이션의 인터페이스를 필요로 하는 경우 그 인터페이스들을 같이 패키징하도록 규정하고 있으므로 다른 애플리케이션의 클로스 로더를 참조할 수 없다.

클래스를 공유해서 사용하지 않기 때문에 한 애플리케이션을 다시 deploy할 때 다른 애플리케이션도 같이 다시 deploy할 필요가 없어진다. 이 클래스 로더 구조를 제대로 사용하기 위해서는 결국 연관된 애플리케이션 간에 EAR로 묶어서 하나의 애플리케이션으로 만드는 작업이 필요하다.

서버는 DOMAIN_HOME 하위에 각자 자신의 디렉터리를 갖는다. DOMAIN_HOME 하위에 servers 디렉터리에는 도메인에 속한 서버들의 디렉터리가 존재한다. 각 서버별로 DOMAIN_HOME/servers 하위에 서버 이름으로 디렉터리를 생성하고, 자신의 서버만의 공간에 운영 중에 필요한 정보나 서버 시작을 위해 필요한 정보 등을 저장한다. 이를 SERVER_HOME이라고 한다.

SERVER_HOME의 디렉터리 구조는 다음과 같다.

{DOMAIN_HOME}
    |--servers
         |--server1
              |--.workspace
              |      |--deployed
              |      |--ejbtimerdb
              |      |--session
              |      |--tmlog
              |      |--tmp
              |--bin
              |--lib
              |   |--application
              |--logs

.workspace

JEUS가 사용하는 서버별 공간으로 사용자가 변경해서는 안 된다.

다음은 하위 디렉터리에 대한 설명이다.

디렉터리설명
deployed

서버에 deploy된 애플리케이션의 압축을 푼 이미지 파일과 deploy할 때 생성되는 파일이 위치한다. 이 디렉터리 하위에는 애플리케이션 ID로 디렉터리가 생기고 Master로부터 받아 온 애플리케이션 파일이 저장된다. 애플리케이션이 archive된 경우 애플리케이션 ID 하위에 압축을 푼다(deploy image).

deployed 디렉터리 하위에 '_generated_'라는 디렉터리가 생성되고 애플리케이션을 deploy할 때 생성되는 파일들이 위치한다. 디렉터리 하위에 애플리케이션 ID로 디렉터리를 생성하고 deploy 시점에 필요한 파일을 생성한다.

ejbtimerdbEJB 엔진의 타이머 서비스에서 DB 설정이 없는 경우 내부적으로 파일 기반의 DB인 JEUS에 내장된 Apache derby를 사용하기 위한 디렉터리이다. 타이머 서비스에 대한 자세한 설명은 JEUS EJB 안내서”의 “제10장 EJB Timer Service”를 참고한다.
session분산식 세션 서버에서 사용하는 파일 DB가 위치한다. 분산식 세션 서버에서는 passivation된 세션과 primary 세션 서버에서 전송한 백업 세션들을 이 파일 DB에 저장한다. 자세한 설명은 JEUS 세션 관리 안내서”의 “제2장 분산 세션 서버”를 참고한다.
tmlog

트랜잭션 복구를 위해 남기는 트랜잭션 로그가 남는 디렉터리이다.

"_serverName_LOCATION_type_port_ipaddress_virtualport 이름"으로 하위 디렉터리가 생성된다. 생성되는 디렉터리 이름에 type과 virtualhost에는 다음의 값이 설정된다.

  • type : IPv4의 경우는 0이 설정되고, IPv6의 경우는 1이 설정된다.

  • virtualport : 서버 이름의 hash 값이 설정된다.

자세한 내용은 “7.5.2. 복구 관련 로그 파일”을 참고한다.

tmp서버 운영 중에 임시로 저장할 파일이 있을 때 사용하는 디렉터리로 사용자가 특별히 접근할 일은 없다.

bin

서버의 시작/종료 스크립트를 포함하고 있다. JEUS_HOME/bin의 스크립트와 동일한 기능을 수행하지만 도메인 이름과 서버 이름을 설정할 필요가 없다.

Master일 경우에 startMasterServer/stopserver, MS일 경우에 startManagedServer/stopserver가 존재한다.

lib/application

서버에 적용하고 싶은 애플리케이션 라이브러리가 위치한다.

DOMAIN_HOME/lib/application에 존재하는 도메인 범위의 라이브러리와 충돌될 경우 이 디렉터리에 존재하는 파일이 적용된다. 도메인의 애플리케이션 라이브러리와 충돌되었다는 경고 메시지를 남기고 도메인 범위의 라이브러리는 이 서버에서 무시된다. lib/application에 대한 자세한 설명은 JEUS Applications & Deployment 안내서”의 “3.3.1. lib/application 디렉터리”를 참고한다.

logs

서버의 Launcher 로그, 서버 로그, 액세스 로그 파일이 저장된다. 각 로그 파일은 로테이션 룰에 따라 "로그 이름_날짜.log00000"으로 생성된다. 00000은 1부터 99999까지의 숫자를 다섯자리로 표현한 것으로 logging에 대한 자세한 내용은 “제8장 Logging”을 참고한다.

JEUS 21에서 MASTER와 MS는 모두 Launcher를 통해서 기동된다. 스크립트를 통해서 서버를 시작시키거나 MASTER를 통해서 MS를 시작시킬 때 모두 Launcher 프로세스를 실행한다. Launcher에서는 서버를 띄우기 위한 준비 작업과 실제 서버를 기동하는 작업을 수행한다.

Launcher의 역할은 크게 2가지가 있다.

  • MASTER 또는 외부 저장소로부터 도메인 설정 파일을 받아오는 작업

  • 서버를 기동시켜주는 작업

Launcher는 먼저 MASTER 또는 외부 저장소로부터 도메인의 설정 파일들을 받아온다. 대상이 되는 파일은 domain.xmlsecurity 설정 파일이다. 설정 파일을 받아오는 작업이 완료되면 Launcher에서는 받아온 설정 파일을 기반으로 서버 JVM을 기동한다. 서버를 기동할 때는 설정 파일에서 시작시킬 서버에 설정되어져 있는 JVM 옵션이나 클래스 패스를 읽어서 서버 JVM을 생성할 때 옵션으로 설정한다.

만약 Launcher 프로세스에서 설정을 받아오는 작업을 실패한 경우 머신에 캐시되어 있는 도메인 설정 파일이 존재할 경우 이 파일을 기반으로 서버 JVM을 기동시킬 것이다. Launcher에서 설정을 받아오는 작업도 실패하고, 머신에도 캐시해놓은 설정 파일이 존재하지 않는다면 서버는 부팅될 수 없다.

Launcher 프로세스는 위의 2가지 역할 외에도 서버 부팅 로그의 logging 역할을 한다.

서버가 부팅하면서 발생한 로그는 Launcher 로그에도 logging이 된다. Launcher 프로세스는 서버 JVM을 기동시키고 서버의 부팅 작업이 모두 완료될 때까지 대기하면서 서버를 부팅할 때 발생한 로그를 logging한다. 만약 서버가 로거를 초기화하기 전에 부팅에 실패했다면 Launcher 로그에서 부팅 실패 원인을 확인할 수 있다.

일반적으로 Launcher 프로세스는 서버의 JVM을 기동하고 해당 서버의 부팅이 완료됨을 확인하면 종료된다. Launcher를 통해 기동된 서버 프로세스는 백그라운드로 수행된다는 것에 유의해야 한다. 또한 서버 프로세스는 Launcher 프로세스의 자식 프로세스로 기동되기 때문에 백그라운드 프로세스로 생성되기 때문에 서버 프로세스는 자신의 콘솔 화면을 갖지 못한다.

따라서 서버의 로그를 콘솔 화면으로 출력하고 싶다면 서버를 실행할 때 -verbose 옵션을 추가해야 한다. -verbose 옵션이 존재하면 Launcher 프로세스는 서버가 종료될 때까지 종료되지 않고 서버의 로그를 화면에 출력하는 역할을 하게 된다. Launcher 로그에 대한 자세한 내용은 “8.2.2. Launcher 로거”를 참고한다.