제2장 웹 컨테이너

내용 목차

2.1. 개요
2.2. 웹 컨테이너 주요 기능과 구조
2.2.1. 주요 기능
2.2.2. 디렉터리 구조
2.3. 웹 컨테이너 설정
2.3.1. 개요
2.3.2. 기본 설정
2.3.3. 자동 모니터링
2.3.4. stdout과 stderr Redirection
2.3.5. Context Group
2.3.6. Database Connection Pool
2.3.7. Session
2.3.8. Logging
2.3.9. Shutdown Timeout
2.3.10. 특정 URL 패턴의 HTTP 요청 방지
2.4. Logging 설정
2.4.1. 공통 설정 항목
2.4.2. Access log 관련 설정 항목
2.4.3. User log 관련 설정 항목
2.5. 웹 컨테이너 제어와 모니터링
2.5.1. 웹 컨테이너 제어
2.5.2. 웹 컨테이너 모니터링

본 장에서는 JEUS 웹 컨테이너의 하위 모듈과 주요 기능, 기본적인 설정 방법에 대해서 설명한다.

2.1. 개요

JEUS 시스템의 웹 컨테이너는 Servlet 2.5와 JSP 2.1 스펙으로 생성된 Java 기술 기반의 동적인 웹 페이지를 실행하기 위한 환경과 운영 기반을 제공한다. 또한 웹 컨테이너는 HTML과 이미지 파일들과 같은 Static Content(정적 콘텐츠)들도 서비스할 수 있다.

웹 컨테이너는 JEUS 웹 모듈의 최상위 컴포넌트이다. 여기에는 많은 수의 하위 모듈들과 설정할 수 있는 기능들이 존재한다. 예를 들어 여러 개의 웹 컨테이너들은 부하 분산과 Failover 기능을 제공하기 위하여 클러스터로 구성될 수도 있고, WebtoB나 Apache 웹 서버와 같은 웹 서버와 연결될 수도 있다.

2.2. 웹 컨테이너 주요 기능과 구조

다음은 웹 컨테이너 컴포넌트로 본 장에서 주로 설명할 부분을 타원으로 표시하고 나머지 부분들은 다음 장에서 설명한다.

[그림 2.1] 웹 컨테이너 구조

웹 컨테이너 구조 웹 컨테이너 구조


다음에 설명하는 하위 절에서는 웹 컨테이너의 가장 중요한 하위 모듈들을 설명한다. 이 모듈들은 각자가 많은 기능들을 포함하고 있지만 여기서 모두 설명하지 않고 별도의 장들에서 설명하도록 한다.

2.2.1. 주요 기능

웹 컨테이너의 하위 모듈들과 기능들은 다음과 같다.

  • 자동 모니터링

    웹 컨테이너 자체 감시의 가장 중요한 부분은 자동 모니터링을 이용하는 것이다. 이 기능은 컨테이너 내의 모든 자원과 Pool들의 상태를 감시하고 문제가 발생하였을 때 대응할 수 있다. 설정에 대한 자세한 내용은 “2.3.3. 자동 모니터링”을 참고한다.

  • stdout와 stderr redirection

    설정 여부에 따라 stdout과 stderr를 사용해서 로그를 남긴다. 설정에 대한 자세한 내용은 “2.3.4. stdout과 stderr Redirection”을 참고한다.

  • Context Group

    각 웹 컨테이너는 하나 이상의 Context Group을 포함할 수 있다. Context Group은 여러 개의 리스너, 가상 호스트, Context를 관리한다. 설정에 대한 자세한 내용은 “2.3.5. Context Group”을 참고한다.

  • Database Connection Pool

    웹 애플리케이션에서는 Database Connection Pool을 생성하여 사용한다. 설정에 대한 자세한 내용은 “2.3.6. Database Connection Pool”을 참고한다.

  • Session 관리

    웹 컨테이너의 Session 관리에 대한 여러 가지 사항을 설정한다. Session 클러스터링의 참여 여부, Session 객체의 공유 여부, Session Cookie 설정, timeout 등 웹 컨테이너의 Session과 관련된 모든 설정을 할 수 있다. 설정에 대한 자세한 내용은 “2.3.7. Session”을 참고한다.

  • Shutdown Timeout

    Shutdown Timeout 기능으로 관리자가 down 명령을 내렸을 때 웹 컨테이너가 실제로 종료되기까지 웹 컨테이너가 기다리는 시간을 지정한다. 설정에 대한 자세한 내용은 “2.3.9. Shutdown Timeout”을 참고한다.

위에서 열거된 목록은 JEUS 웹 컨테이너의 최상위 뷰를 표현하고 있다. 이들은 웹 컨테이너의 주요 하위 모듈인 Context Group과 Context가 사용할 수 있는 모듈들과 서비스들을 의미한다.

2.2.2. 디렉터리 구조

다음은 JEUS 웹 컨테이너를 다룰 때 가장 많이 사용되는 디렉터리들이다.

[그림 2.2] JEUS 웹 컨테이너 관련 디렉터리

JEUS 웹 컨테이너 관련 디렉터리


JEUS_HOME

JEUS가 설치된 최상위 디렉터리이다.

config\<node-name>

JEUS Manager 및 컨테이너에 대한 설정 파일인 JEUSMain.xml을 가지고 있다.

config\<node-name>\<node-name>_servlet_<engine-name>\

웹 컨테이너의 모든 설정이 포함된 WEBMain.xml 파일이 포함되어 있다.

webhome

웹 애플리케이션을 위한 home 디렉터리로서 다음과 같은 작업 디렉터리를 가지고 있다.

디렉터리설명
app_home

엔진 로딩 후에 디플로이 대상이 되는 웹 애플리케이션이 존재하며 그 형태는 archive 타입과 exploded 타입 모두 가능하다.

콘솔 툴(jeusadmin)이나 WebAdmin을 통해서 디플로이할 경우 이 작업 디렉터리를 사용한다.

autodeploy엔진을 기동(Booting)하는 경우 archive 타입의 웹 애플리케이션을 엔진이 자동으로 디플로이한다.
<nodeName_containerName>

웹 애플리케이션이 디플로이될 경우 사용하는 작업 디렉터리이다.

만일 JSP 관련해서 생성되는 파일에 위치를 지정하고 싶을 경우 WEBMain.xml 이나 jeus-web-dd.xml의 <jsp–engine> 요소를 통해서 설정이 가능하다.

로그는 웹 컨테이너를 통해 직접적으로 생성되지 않고 Context Group 레벨에서 설정하고 생성된다. 자세한 내용은 “제3장 Context Group”을 참고한다.

2.3. 웹 컨테이너 설정

본 절에서는 JEUS 웹 컨테이너의 주요 기능에 대한 설정 방법에 대해서 설명한다.

2.3.1. 개요

웹 컨테이너 설정하기 위해서는 기본 설정 파일인 JEUSMain.xmlWEBMain.xml이 필요하다.

WEBMain.xml은 JEUSMain.xml에 추가된 JEUS 웹 컨테이너를 설정하는 파일로 웹 컨테이너의 설정 디렉터리에 해당 파일이 존재해야한다. WEBMain.xml의 수정은 XML 파일을 직접 편집하거나 WebAdmin을 사용하여 설정을 할 수 있다.

WEBMain.xml 파일에는 웹 컨테이너 설정의 여러 부분을 대표하는 태그들이 존재한다. 각 태그들을 다음 하위 절에서 설명한다. Context Group과 Session 설정의 일부는 본 절에서 간략히 설명하고 좀 더 자세한 내용은 별도의 장의 내용을 참고한다.

참고

본 장에서 설명하는 설정에 대한 내용은 WebAdmin을 이용해서 설정할 수 있다. WebAdmin을 이용해서 JEUSMain.xml에 웹 컨테이너 추가 방법과 WEBMain.xml 파일을 설정하는 자세한 내용은 "JEUS WebAdmin 안내서"의 엔진 컨테이너와 서블릿 엔진 부분을 참고한다.

2.3.2. 기본 설정

다음은 웹 컨테이너의 기본 설정 파일인 JEUSMain.xml의 예이다.

[예 2.1] 웹 컨테이너 기본 설정 : <<JEUSMain.xml>>

<?xml version="1.0"?>
<jeus-system xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
    . . .
    <node>
        . . .
        <engine-container>
            . . .
            <engine-command>
                <type>servlet</type>
                <name>engine1</name>
            </engine-command>
            . . .
        </engine-container>
        . . .
    </node>
    . . .
</jeus-system>


<engine-command> 태그가 JEUS 기동(Booting) 과정에 사용되기 위해서는 다음 디렉터리가 존재해야 한다. 해당 디렉터리 아래에는 반드시 WEBMain.xml이라는 파일이 존재해야 한다.

JEUS_HOME\config\<node-name>\<node-name>_servlet_<engine-name>

다음은 디렉터리명을 설정하는 항목에 대한 설명이다.

항목설명
<node-name>JEUS의 노드명이다.
<engine-name>JEUSMain.xml의 <engine-name>의 하위 태그인 <name>에 설정된 값이어야 한다. 위의 예제에서 'hostname'이 'johan'이라면 <engine-name>은 'johan_servlet_engine1'이 된다.

참고

각 엔진 컨테이너에는 단 한 개의 웹 컨테이너가 존재할 수 있다.

2.3.3. 자동 모니터링

웹 컨테이너 자체 감시의 가장 중요한 부분은 자동 모니터링을 이용하는 것이다. 자동 모니터링은 웹 컨테이너의 자동 관찰 시스템이다. 이 기능은 컨테이너 내의 모든 자원과 Pool들의 상태를 감시하고 문제가 발생하였을 때 대응할 수 있는 기능을 한다.

자동 모니터링에는 다음이 3가지가 존재한다.

구분설명
Thread Pool Monitor컨테이너의 Worker Thread Pool을 모니터링한다. 자세한 내용은 “제4장 웹 서버 연결과 클러스터링”을 참조한다.
Class-reloading Monitor웹 컨테이너에 등록된 Servlet 클래스들의 변경을 모니터링한다. 자세한 내용은 “제6장 Web Context(웹 애플리케이션)”를 참조한다.
Session Monitor클라이언트 Session 기한 만료를 모니터링하고 사용되지 않는 Session을 제거한다. 자세한 내용은 “제5장 Session Tracking”을 참조한다.

관리자는 모니터링을 하기 위해서 상태를 파악하기 위한 시간 간격을 설정해야 한다. 모니터링 Thread가 사용하는 시간 주기를 WEBMain.xml의 <monitoring> 태그와 그 하위 태그에 설정한다. 자세한 내용은 JEUS_HOME\docs\reference\schema\index.html에서 WEBMain.xml XML Reference를 참조한다.

다음은 자동 모니터링을 설정한 XML 예제이다.

[예 2.2] 자동 모니터링 설정 : <<WEBMain.xml>>

<?xml version="1.0"?>
<web-container xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
    <monitoring>
        <check-thread-pool>60000</check-thread-pool>
        <check-class-reload>60000</check-class-reload>
        <check-session>60000</check-session>
    </monitoring>
    . . .
</web-container>


문제가 발생한 경우 각 모니터링 Thread의 하위 컴포넌트에 해당하는 XML 설정 부분에서 따로 설정한다.

2.3.4. stdout과 stderr Redirection

웹 컨테이너는 자체적으로 WEBMain.xml에는 2개의 태그들이 stdout과 stderr Redirection을 위해 설정되고 다음 디렉터리에 로그를 남기는 기능을 제공하고 있다. 그러나 이 기능은 JEUS 시스템 로거에 의해 같은 기능이 포함되어 있으므로 앞으로 이 기능은 설정하지 않도록 한다. 자세한 사항은 JEUS Server 안내서”의 “11.3.3. 표준 출력과 표준 에러를 로그 형식으로 출력 설정”을 참고한다.

2.3.5. Context Group

각 웹 컨테이너는 하나 이상의 Context Group을 포함할 수 있다.

Context Group은 개별적인 작은 웹 컨테이너로 Group은 여러 개의 리스너, 가상 호스트, Context를 관리한다. Context는 컨테이너에서 수행되는 실제 웹 애플리케이션과 같은 개념이다. Context Group은 그 안에 포함된 모든 Context와 가상 호스트에 공통적으로 적용되는 설정과 서비스들을 가지고 있다.

Context Group의 또 한 가지 중요한 기능은 웹 서버 연결과 클러스터 환경에서의 Session Handling과 Active Management이다.

참고

Context Group은 많은 양의 설정을 담고 있으므로 “제3장 Context Group”에서 따로 상세히 설명한다. Context에 대한 자세한 내용은 “제6장 Web Context(웹 애플리케이션)”에서 설명하고, 가상 호스트는 “제7장 가상 호스트”에서 설명한다.

Context Group은 여러 개의 웹 애플리케이션 또는 가상 호스트를 관리하는 컨테이너이다. 각 웹 컨테이너에는 하나 이상의 Context Group이 존재할 수 있고, WEBMain.xml의 최상위 태그인 <context-group>을 이용하여 설정된다.

[예 2.3] Context Group 설정 : <<WEBMain.xml>>

<?xml version="1.0"?>
<web-container xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
    <monitoring>
        . . .
    </monitoring>
    . . .
    <context-group>
        . . .    <!-- See chapter “제3장 Context Group” -->
    </context-group>
    <context-group>
        . . .
    </context-group>
        . . .
</web-container>


웹 컨테이너 레벨에서 정의된 설정들은 모든 Context Group과 웹 컨테이너의 하위 Context에 글로벌하게 적용된다.

2.3.6. Database Connection Pool

JEUS v5.0 Fix13 이전까지 웹 컨테이너는 독립적인 DB Connection Pool을 사용했다. 그러나 JEUS v5.0 Fix#13 이후 버전에서는 javax.sql.DataSource를 사용하도록 변경되었다. 그래서 JEUSMain.xml에 DB Connection Pool을 등록하고 JNDI lookup을 이용해서 Datasource를 얻은 다음 DB Connection을 얻어야 한다.

2.3.7. Session

웹 컨테이너의 Session을 관리하기 위한 여러 가지를 설정한다.

Session 클러스터링의 참여 여부, Session 객체의 공유 여부, Session Cookie 설정, Timeout 등 웹 컨테이너의 Session과 관련된 모든 설정을 할 수 있다. 추가적으로 클러스터링된 환경에서의 Session에 대한 사항은 “제5장 Session Tracking”에서 설명한다.

웹 컨테이너의 Session과 관련된 여러 가지 설정을 할 수 있다. Session 설정은 웹 컨테이너 외에도 다음의 여러 레벨에서 설정이 가능하다.

구분설명
Web Container 레벨WEBMain.xml의 <web-contianer> 하위 <session-config> 태그
Context Group 레벨WEBMain.xml의 <context-group> 하위
Context 레벨jeus-web-dd.xml의 <jeus-web-dd> 하위

Web Container 레벨에서 Session 설정이 되어 있다면 하위 Context Group 또는 jeus-web-dd에 Session 설정하지 않았을 경우 공통적으로 웹 컨테이너의 Session 설정 부분이 적용된다.

참고

Web Container 레벨, Context Group 레벨, Context 레벨의 설정이 중복되었을 경우 하위 레벨의 세부적인 설정에 가장 높은 우선순위를 부여한다. 즉, 세 군데 모두 설정을 하였다면 Context 레벨 > Context Group 레벨 > Web Container 레벨 순으로 설정값이 적용된다.

만약 하위 레벨에서 특정 설정을 하지 않았다면 상위 레벨의 설정값을 적용하고 모든 레벨에서 설정하지 않은 값은 엔진 내부적인 기본값으로 동작한다.

다음은 Web Container 레벨의 Session 설정의 예이다. Session 설정은 <web-contianer> 하위 <session-config>에 설정한다.

[예 2.4] Session 설정 : <<WEBMain.xml>>

<?xml version="1.0"?>
<web-container xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
    . . .
    <session-config>
        <distributable>false</distributable>
        <shared>false</shared>
        <timeout>30</timeout>
        <reload-persistent>false</reload-persistent>
        <url-rewriting>false</url-rewriting>
        <session-cookie>
            <jsessionid-name>JSESSIONID</jsessionid-name>
            <version>0</version>
            <path>/</path>
            <max-age>-1</max-age>
            <secure>false</secure>
            <http-only>true</http-only>
        </session-cookie>
    </session-config>
    . . .
</web-container>

다음은 설정 태그에 대한 설명이다.

  • <distributable>

  • <shared>

    • 현 Context에서 생성된 Session 객체를 다른 Context들에서도 공유하여 사용할지의 여부를 설정한다. 즉, Context A에서 생성된 HTTPSession 객체가 Context B에서도 같은 사용자에 의해 사용될 수 있는지에 대한 것이다.

    • Session 클러스터링이 아닌 환경의 경우 최대 공유 범위는 동일 애플리케이션 내의 Context이며, Session 클러스터링 환경의 경우 공유 범위는 제한이 없다.

    • Boolean 형식의 설정이며, 설정하지 않았을 경우 기본값으로 false가 설정된다.

  • <timeout>

    • 생성된 Session 객체의 유효 주기를 설정한다.

      보통 웹 애플리케이션 설정인 web.xml에서 Session의 timeout을 설정하지만, web.xml에서 특별한 설정을 하지 않았다면 JEUS의 Session 설정 즉, <session-config><timeout>에서 설정한 값이 적용된다. 다시 말하면, web.xml의 Session timeout 설정이 존재한다면 현 설정값은 적용되지 않는다(web.xml의 Session timeout이 가장 우선순위가 높다).

    • Int 형식으로 분 단위의 시간을 설정한다. 설정하지 않았을 경우 기본값으로 30(30분)이 설정된다.

    참고

    위의 설정 shared가 true일 경우 즉, Session이 여러 Context들 간에 공유가 된다면 해당 Session의 timeout은 JEUS 웹 컨테이너에서는 해당 Session이 처음 생성되는 Context의 timeout 설정을 따르도록 한다.

  • <reload-persistent>

    • 일반적으로 Servelet Context가 변경되어 리로딩이 발생할 때 해당 Context 내의 Session 객체의 속성들은 모두 삭제된다. 하지만, <reload-persistent>가 true로 설정되어 있으면 Session 객체의 속성들을 계속 유지시켜 준다.

    • Boolean 형식으로 설정하며, 설정하지 않았을 경우 기본값으로 false가 설정된다.

  • <url-rewriting>

    • -1 값의 의미는 쿠키의 expires 속성을 ID를 여러 번 요청 중에도 지속적으로 유지하기 위하여 쿠키를 사용한다.

      문제는 만약에 요청과 함께 쿠키가 처음 생성된 곳의 도메인 이름이 요청이 생성된 곳의 이름과 다르면 대부분의 브라우저 Session 쿠키 정보를 보내지 않는다는 것이다.

      설정값설명
      true

      쿠키에 의존하는 대신에 URL rewriting을 강제로 대신 사용하게 한다.

      이렇게 함으로써 Session Tracking이 다른 도메인 이름이 사용되어 몇 번의 요청이 들어와도 가능하게 된다. URL rewriting이라 함은 Context에 의해 반환되는 모든 URL에 유일한 JSESSIONID URL 파라미터를 붙이는 것을 의미한다.

      false이 기능은 사용되지 않고, 기본적인 쿠키 기반만 사용된다. (기본값)

  • <session-cookie>

    • 사용자의 Session을 추적하는 기본 기술은 모든 클라이언트 응답에 반환되는 이 Session 쿠키를 이용한다. 자세한 내용은 “제5장 Session Tracking”을 참고한다.

    • 웹 컨테이너에서 Response를 내보낼 때 HTTP 헤더의 Session 쿠키에 대한 설정을 여기서 한다. 일반적으로 엔진에서 쿠키를 구성하나, 특별한 쿠키 정보를 구성하는 경우 사용한다.

    • 다음과 같은 세부 항목을 설정할 수 있다.

      태그설명
      <jsessionid-name>

      Session 쿠키의 이름으로 표준 이름인 "JSESSIONID"을 사용하지 않고 다른 이름을 사용할 때 이 설정을 사용한다.

      String 형식으로 설정하고, 설정하지 않았을 경우 기본값으로 "JSESSIONID"가 설정된다.

      <version>

      쿠키의 버전을 설정한다. Int 형식의 설정으로 다음의 값 중에 하나를 설정한다.

      • 0 : NS 쿠키 유형을 가진다. (기본값)

      • 1 : RFC 스펙의 쿠키 유형을 가진다.

      <domain>

      Session 쿠키가 보내질 때 서버의 도메인 이름을 설정한다. 쿠키는 이 도메인 요청에 대해서만 되돌아온다. 하나의 적합한 도메인 이름은 "."으로 시작되어야 하며 <host_name>을 지정해서는 안 된다. 이에 대한 자세한 내용은 RFC-2109 스펙을 확인한다.

      String 형식의 설정이며, 설정하지 않았을 경우 쿠키에 도메인 정보를 포함하지 않도록 한다.

      <path>

      Session 쿠키가 보내질 도메인 내의 URL 경로를 설정한다. 쿠키는 도메인이 적합할 때 해당 URL의 어떤 요청과 더불어 보내진다.

      예를 들어 만일 "/examples"란 경로가 설정되고, 도메인은 ".foo.com"으로 설정되었다고 가정할 때, 클라이언트의 요청들은 "www.foo.com/examples"의 형식에 맞을 때만 해당 쿠키를 포함하여 서버로 요청한다. 이 또한 위의 도메인 설정과 더불어 RFC-2109 스펙을 확인한다.

      String 형식의 설정이며, 설정하지 않았을 경우 엔진 내부에서 적절한 path를 선택하고 설정을 하였을 경우 일반적으로 설정된 고정 path 정보를 쿠키에 포함한다. path를 설정할 경우 설정한 고정 값이 항상 쿠키의 정보로 포함된다.

      path의 최상위 값인 "/"가 아닌 다른 값으로 설정을 할 경우는 애플리케이션들의 Session 공유 특성들을 고려하여 주의 깊게 값을 설정한다.

      <max-age>

      Session 쿠키의 expires 속성을 설정한다. 이 시간 주기가 되면 쿠키는 클라이언트로부터 제거되고 더 이상 보내지지 않는다. 설정값은 Int 형식으로 단위는 초이다.

      값을 설정하지 않았을 경우 기본값으로 -1이 설정된다. -1 값의 의미는 쿠키의 expires 속성을 사용하지 않겠다는 것을 의미한다. 즉, 브라우저의 Lifecycle을 따르겠다는 의미로서 브라우저가 닫힐 때 쿠키는 사용자의 Session이 끝남과 동시에 끝난다.

      <secure>

      Session 쿠키의 secure 속성을 설정한다.

      만일 true로 설정되면 Session 쿠키는 오직 secure http connection인 HTTPS 위에서만 보내진다.

      Boolean 형식이며, 설정하지 않았을 경우 기본값으로 false가 설정된다.

      <http-only>

      세션 쿠키가 HTTP 외의 Script 요청에 의해서 사용되는 것을 방지하는 보안기술을 설정한다.

      Boolean 형식이며, 설정하지 않았을 경우 기본값으로 true가 설정된다.

2.3.8. Logging

웹 컨테이너에서 생성되는 로그 메시지는 System log, User log, Access log 3가지이다.

System log는 JEUSMain.xml에서 <system-logging>을 통해 설정한다. User log 및 Access log는 WEBMain.xml의 <logging>을 통해 설정한다. Logging 설정은 웹 컨테이너 전체 또는 하위 Context Group별로 따로 설정할 수 있다. Logging 설정에 대한 자세한 내용은 “2.4. Logging 설정”에서 설명한다.

2.3.9. Shutdown Timeout

Shutdown Timeout 기능은 관리자가 down 명령을 내렸을 때 웹 컨테이너가 실제로 종료되기까지 웹 컨테이너가 기다리는 시간을 지정한다. 이 설정은 관리자가 웹 컨테이너는 Worker Thread들이 작업을 모두 마치기까지 기다리도록 한다.

down 명령을 수행했을 때 어떤 Worker Thread도 실행되고 있지 않으면 컨테이너는 이 설정을 무시하고 바로 종료를 수행한다.

다음은 Shutdown Timeout 설정에 대한 예로 <web-container> 태그에 <shutdown-timeout> 하위에 구성한다.

<?xml version="1.0"?>
<web-container xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
    . . .
    <shutdown-timeout>10000</shutdown-timeout>
</web-container>

2.3.10. 특정 URL 패턴의 HTTP 요청 방지

만약 HTTP 클라이언트가 다음과 같은 요청을 보냈다고 하자.

GET /examples/%2e%2e%2fdb.txt HTTP/1.1

이 경우 웹 컨테이너는 먼저 요청 URI를 URL decode해야 한다.

/examples/../db.txt

이렇게 되면 실제 HTTP 서비스와는 관련없는 파일들을 접근할 수 있게 된다. 주로 악의적인 목적을 가진 클라이언트가 이런 식으로 요청 URI을 보낸다.

웹 컨테이너에서 모든 악의적인 요청 패턴을 파악할 수 없으므로 사용자가 직접 악의적인 패턴을 막을 수 있도록 설정을 제공한다. HTTP 요청인 경우에만 동작하며, Query String을 제외한 URI에 대해 특정 문자열을 매칭해서 무조건 404 Not Found로 처리한다.

프로퍼티 파일에 다음의 형식으로 설정한다.

#URL-encoded patterns
encodedUrl1=%2f
encodedUrl2=%2e
encodedUrl3=%5c
encodedUrl4=test
 
#URL-decoded patterns
decodedUrl1=\
decodedUrl2=#
decodedUrl3=::$
decodedUrl4=test

URL-encoded 패턴은 HTTP 클라이언트가 보낸 URI에 대해 설정된 문자열을 포함하는지 체크하는 것이고, 해당 URI를 웹 컨테이너가 URL decode한 다음에 URL-decoded 패턴이 decode한 URI에 포함되어 있는지 매칭해 본다.

위 프로퍼티 파일의 절대 경로를 jeus.servlet.url-blocking-properties 옵션으로 지정한다.

-Djeus.servlet.url-blocking-properties=/jeus/blockedUrlPatterns.properties

참고

웹 컨테이너는 위 설정과 관계없이 URL-encoded 패턴의 경우 %2e, %2f, %5c, %23, %00, URL-decoded 패턴은 '#'에 대해서 404 응답 처리를 한다.

2.4. Logging 설정

웹 컨테이너에서 별도로 설정 가능한 Logger는 Access log와 User log이다. 별도의 설정이 없을 경우 웹 컨테이너 당 1개의 Access log 및 User log 파일이 생성된다.

다음은 JEUS log의 기본 위치(JEUS_LOGHOME)이다.

JEUS_HOME\logs\<node-name> 

  • Access log

    • 웹 컨테이너에 요청된 request 및 그 처리 결과에 대한 로그이다.

    • 기본 위치

      기본 로그 파일은 다음의 위치에 생성이 된다.

      JEUS_LOGHOME\<node-name>_<container-name>\servlet\accesslog\<GroupName>\access.log

      다음은 JEUS_HOME이 'c:\jeus6'이고, node_name이 'johan', container_name이 'container1'인 경우 기본 로그 파일이다.

      c:\jeus6\logs\johan_container1\servlet\accesslog\access.log
  • User log

    • javax.servlet.ServletContext.log(String msg) 또는 javax.servlet.ServletContext.log(String msg, Throwable t) 등의 API를 사용하여 Servlet 애플리케이션 내에서 생성되는 메시지를 기록하는 로그이다.

    • 기본 위치

      다음의 위치에 로그 파일이 생성된다.

      JEUS_LOGHOME\<node-name>_<container-name>\servlet\userlog\<GroupName>\user.log 

      다음은 JEUS_HOME이 'c:\jeus6'이고, node_name이 'johan', container_name이 'container1'인 경우 로그 파일이다.

      c:\jeus6\logs\johan_container1\servlet\userlog\user.log

2.4.1. 공통 설정 항목

본 절에서는 Access log과 User log 설정 항목 중 공통으로 적용되는 설정 정보에 대해서 설명한다.

설정 정보는 <context-group> 태그 아래 <logging>에 구성한다. <access-log>와 <user-log>는 <logging> 설정의 하위 요소이며 <context-group> 단위로 설정이 가능하다.

<logging> 설정은 다음의 예제와 같이 <web-container> 또는 <context-group>의 하위 요소로 존재한다. <web-container> 설정의 하위 요소로 <logging>을 설정하면 <web-container> 내의 모든 <context-group>에 공통으로 적용된다. <context-group>의 하위 요소로 설정된 <logging>은 해당 <context-group>에만 적용되며 <web-container>의 <logging> 설정보다 우선한다.

참고

<web-container> 하위에는 <access-log>를 설정하지 않아도 기본적으로 Logging을 하도록 되어있다. 이때 의도하지 않게 하나의 파일에 너무 많은 양의 Logging이 될 수 있으므로 JEUS v6.0 Fix #8부터는 <web-container> 하위에 <access-log> 설정이 없으면 <log rotation> 정책을 적용하여 Logging하도록 한다. 웹 컨테이너에 Access log가 생성되는 것을 원하지 않으면 <enable>을 false로 설정한다.

다음은 웹 컨테이너 Logging 설정에 대한 예이다.

[예 2.5] 웹 컨테이너 Logging 설정 : <<WEBMain.xml>>

<?xml version="1.0"?>
<web-container xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
    <context-group>
    . . .
        <logging>
            <user-log>
                <level>FINE</level>
                <use-parent-handlers>
                    true
                </use-parent-handlers>
                <handler>
                    <smtp-handler>
                        <name>smtpHandler</name>
                        <level>SEVERE</level>
                        <smtp-host-address>
                            mail.com
                        </smtp-host-address>
                        <from-address>
                            jeus@mail.com
                        </from-address>
                        <to-address>
                            admin@mail.com
                        </to-address>
                        <send-for-all-messages>
                            false
                        </send-for-all-messages>
                    </smtp-handler>
                </handler>
            </user-log>
            <access-log>
                <enable>true</enable>
                <format>
                    [%{yyyy.MM.dd HH:mm:ss}t] %a %m %U%q" %s %Dms 
                </format>
                <handler>
                    <file-handler>
                        <name>fileHandler</name>
                        <valid-hour>1</valid-hour>
                    </file-handler>
                </handler>
            </access-log>
        </logging>
    </context-group>
    . . .
</web-container>


다음은 <access-log>, <user-log>에 공통으로 설정하는 항목에 대한 설명이다.

  • <level>

    • logger의 레벨을 설정한다. 이 레벨 이하의 메시지만 Logger를 통해 출력될 수 있다.

    • <level>의 값으로는 Logging API의 레벨인 다음 중에 하나를 설정한다.

      • SEVERE

      • WARNING

      • INFO(기본값)

      • CONFIG

      • FINE

      • FINER

      • FINEST

    주의

    <access-log> 설정에서 <level> 설정은 무의미하다.

  • <use-parent-handlers>

    • Logger가 자신의 handler뿐만 아니라 상위 Logger의 handler를 사용할 것인지의 여부를 지정한다. (기본값: true)

  • <filter-class>

    • Logger가 로그 메시지를 handler에게 보내기 전에 수행하는 필터링에 사용할 클래스를 지정한다.

      여기에 지정된 클래스는 lib\application 디렉터리의 JAR 파일 내에 포함되어야 한다.

  • <handler>

    • logger가 사용할 handler를 지정한다. 이 항목이 설정되어 있지 않다면 access-log의 경우는 기본적으로 file handler가 사용되고, user-log의 경우는 console handler와 file handler가 사용된다.

    • <handler>에는 다음과 같은 하위 항목들이 있다.

      • <console-handler>

        화면으로 로그 메시지를 출력하는 handler이다. 이 handler는 다음과 같은 기본적인 설정만 가지고 있다.

        태그설명
        <name>handler가 툴에서 보여질 때 사용할 이름을 지정한다. 만약 지정되어 있지 않으면 class name과 hash code로 이름이 대체된다.
        <level>

        handler가 출력할 메시지의 레벨을 지정한다. 즉, Logger를 통과한 로그 메시지가 이 Logger가 사용하는 각각의 handler에게 전달되는데 이 handler의 레벨에 부합하는 로그 메시지만 이 handler에 의해 출력된다.

        기본값은 FINEST로 Logger를 통과하는 모든 로그 메시지가 handler에 의해 출력되도록 되어 있다. 단, Access log일 경우 INFO 레벨 이상에서는 Access log를 출력하지 않는다.

        <encoding>

        handler가 출력하는 문자열의 인코딩을 지정한다.

        한글 querystring의 출력을 지원하기 위해서 기본값은 system encoding이 아닌 'ISO-8859-1'로 설정되어 있다. HttpServletRequest.getQueryString()은 스펙에 따라 WEBMain.xml에 인코딩 설정이 있어도 디코딩 처리를 하지 않기 때문에 'ISO-8859-1'로 디코딩해야 Access log에 한글 querystring이 정상적으로 출력된다.

        <filter-class>

        handler가 로그 메시지를 출력하기 전에 수행할 필터링에 이용되는 클래스이다.

        Logger의 <filter-class>와 마찬가지로 lib\application에 이 클래스를 포함한 JAR 파일이 존재해야 한다.

      • <file-handler>

        파일로 로그 메시지를 출력하는 handler로 <console-handler>의 설정 이외에 다음과 같은 설정을 가지고 있다.

        태그설명
        <file-name>

        handler가 출력할 파일의 이름을 지정한다.

        절대 경로로 되어 있다면 그 경로로 파일이 생기고 상대 경로라면 각 Logger의 기본 경로를 기준으로 한 상대 경로로 인식한다. 이 설정을 하지 않으면 각 Logger별로 지정된 path로 파일을 생성해서 로그 메시지를 출력한다.

        <valid-day>,

        <valid-hour>

        handler가 출력할 파일을 시간마다 따로 생성할 경우에 사용한다.

        둘 중 하나만 사용할 수 있는데 <valid-day>는 날짜별로 <valid-hour>는 시간별로 파일을 변경한다.

        <valid-hour>는 24의 약수이거나(ex. 3, 6) 24로 나눈 나머지가 약수(ex. 27, 30)의 이름을 지정한다.

        파일 이름의 형식은 <valid-day>의 경우 파일 끝에 '_YYYYMMDD'가 붙거나, <valid-hour>의 경우 '_YYYYMMDD_HH'가 붙는다. 이때 HH는 파일 로그의 시작 시간이다.

        <buffer-size>

        파일로 출력할 때 사용할 버퍼의 크기를 지정한다.

        버퍼가 클수록 Logging의 성능은 좋아지지만 예상치 못한 상황으로 JEUS가 종료될 때에는 그 버퍼 크기만큼 로그가 손실된다. (기본값: 20KB)

        <append>파일로 출력할 때 이미 파일이 존재하면 덮어쓸지 파일끝에 추가할지를 결정한다. (기본값: true)
        <log rotation>JEUS Server 안내서”의 “11.3.2. 로그 파일 Rotation 설정”을 참고한다.
      • <smtp-handler>

        로그 메시지를 e-mail로 전송하는 handler이다. 하나의 로그 메시지가 하나의 e-mail로 전송된다. <console-handler>의 설정 이외에 다음과 같은 설정을 가지고 있다.

        태그설명
        <smtp-host-address>e-mail을 보낼 호스트의 주소를 지정한다.
        <from-address>e-mail을 보내는 사람의 주소를 지정한다.
        <to-address>e-mail을 받는 사람의 주소를 지정한다.
        <cc-address>e-mail을 참조하는 사람의 주소를 지정한다.
        <bcc-address>e-mail을 숨은 참조하는 사람의 주소를 지정한다.
        <send-for-all-messages>

        모든 메시지를 smtp-handler로 보낼지를 결정한다.

        false인 경우 JEUS 시스템에서 e-mail로 전송하기로 결정되어 있는 메시지만 이 handler를 사용해서 보내진다. 이 설정은 jeus.systemuser logger에만 유효하다.

      • <socket-handler>

        로그 메시지를 소켓으로 전송하는 handler로 <console-handler>의 설정 이외에 다음과 같은 설정을 가지고 있다.

        태그설명
        <address>handler가 접속할 머신의 IP 주소를 지정한다.
        <port>handler가 접속할 머신의 port를 지정한다.

      • <user-handler>

        사용자가 생성한 handler 클래스를 지정하는 항목으로 <console-handler>의 설정 이외에 다음과 같은 설정을 가지고 있다.

        태그설명
        <handler-class>

        사용자가 생성한 handler의 클래스를 지정한다.

        이 클래스는 lib\application 디렉터리의 jar 파일에 포함되어 있어야 한다. 또한 이 클래스는 Logging API의 java.util.logging.Handler를 상속받고 jeus.util.logging.JeusHandler를 구현해야 한다.

        <handler-property>jeus.util.logging.JeusHandler의 setProperty()에 사용되는 Map 객체에 들어갈 프로퍼티를 지정한다.
        <formatter-class>

        handler가 사용할 formatter 클래스를 지정한다.

        이 클래스도 lib\application 디렉터리의 jar 파일에 포함되어 있어야 한다. 또한 jeus.util.logging.JeusFormatter interface를 구현해야 한다. 기본값은 JEUS에서 사용하는 jeus.util.logging.SimpleFormatter이다.

        <formatter-property>jeus.util.logging.JeusFormatter의 setProperty()에 사용되는 Map 객체에 들어갈 프로퍼티를 지정한다.

2.4.2. Access log 관련 설정 항목

다음은 Access log에만 사용되는 설정에 대한 설명이다.

  • <access-log>

    태그설명
    <enable>Access log 관련하여 아무것도 설정하지 않을 경우 기본 파일에 기본 형식으로 Access log를 남긴다. 이 설정은 Access log를 남기는 것을 원치 않을 경우 사용한다.
    <format>Access log에 남길 로그의 형식을 지정한다. 설정하지 않을 경우 기본 형식으로 로그를 남긴다. 자세한 설명은 "<access-log>의 <format> 설정"을 참고한다.
    <exclude-ext>특정 확정자들을 콤마(,)로 구분하여 설정한다.

<access-log>의 <format> 설정

<access-log>의 하위 요소인 <format>을 사용하여 사용자 정의 Access log format을 지정하는 것이 가능하다. <format>에 넣을 값은 임의의 String 값이 가능하다. 단, “%” 기호는 특수 기호로 인식된다. 즉, “%”를 접두사로 사용하는 다음에 열거하는 단어들은 runtime에 여러 가지 request/response property로 대체되어 Access log에 남게 된다.

  • 기본 <format>

    [%{yyyy.MM.dd HH:mm:ss}t] %a "%m %U%q" %s %Dms
  • Runtime에 대체되는 특수 단어들1

    단어설명
    %aRemote IP address
    %ALocal IP address
    %bHTTP header를 제외한 response body의 총 길이 ('-'는 0을 나타낸다)
    %BHTTP header를 제외한 response body의 총 길이
    %hRemote host name 또는 IP address
    %HRequest protocol
    %mRequest method (GET, POST…)
    %pLocal port number
    %qQuery string( 앞에 ‘?’가 붙음)
    %rmethod 와 request URI
    %sHTTP response status code
    %SUser session ID
    %tDate and time (기본 시간 형식. 후술함)
    %uRemote user name
    %URequest URL
    %vLocal server name
    %Dprocessing time (단위: ms)
    %Tprocessing time (단위: 초)
  • Runtime에 대체되는 특수 단어들2

    request cookie, header, attribute, session attribute 등에서 특정 값을 가져와 표시할 수 있다.

    단어설명
    {xxx}Irequest header에서 key가 “xxx”인 값을 표시한다.
    {xxx}crequest cookie에서 key가 “xxx”인 값을 표시한다.
    {xxx}rrequest attribute에서 key가 “xxx”인 값을 표시한다.
    {xxx}sSession 정보에서 key가 “xxx”인 값을 표시한다.
    {xxx}t“xxx”를 JDK standard DateFormat으로 기술하면 access-log의 시간 형식을 바꿀 수 있다.

Access log 필터 설정

사용자의 특별한 설정이 없을 경우 다음과 같은 기본 형식의 모든 Access log를 기록한다.

[2010.06.22 14:42:57] 127.0.0.1 "GET /examples/images/bluebtn.gif" 404 0ms

하지만 보통 Access log의 양은 상당히 많기 때문에 특정 형식 또는 조건을 만족하는 로그만 Access log로 기록하고 싶을 경우가 때때로 존재한다. 이를 위해 제공되는 기능이 Access log 필터 기능이다.

Access log 필터 기능 지원을 위해 JEUS에서는 jeus.util.AccessLoggerFilter 인터페이스 및 jeus.util.AbstractAccessLoggerFilter 추상 클래스를 제공하고 있다.

다음은 jeus.servlet.util.AccessLoggerFilter 인터페이스의 상세 내용이다.

package jeus.servlet.util;

import java.util.logging.Filter;
import java.util.logging.LogRecord;

/**
 * Access Logger의 내용을 필터링 하기위해 필요한 정보들을 제공하는 인터페이스.
 * {@link Filter}를 상속한 필터 인터페이스로서 부수적으로 제공되는 인터페이스를 통해
 * {@link Filter#isLoggable(java.util.logging.LogRecord)}안에서 다양하게 필터링 정책을 정하도록 가이드 한다.
 */
public interface AccessLoggerFilter extends Filter {
    /**
     * 서버에 접속한 remote client의 address 정보를 반환한다.
     *
     * @param record a LogRecord
     * @return remote client의 address. 만약 올바른 값을 얻지 못할 경우 null을 반환한다.
     */
    public String getRemoteAddr( LogRecord record );

    /**
     * 요청의 메소드를 반환한다. ex) GET, POST, PUT, etc...
     *
     * @param record a LogRecord
     * @return request method. 만약 올바른 값을 얻지 못할 경우 null을 반환한다.
     */
    public String getMethod( LogRecord record );

    /**
     * 요청의 uri를 반환한다.
     *
     * @param record a LogRecord
     * @return request uri. 만약 올바른 값을 얻지 못할 경우 null을 반환한다.
     */
    public String getRequestURI( LogRecord record );

    /**
     * 응답의 status값을 반환한다. ex) 200, 404
     *
     * @param record a LogRecord
     * @return status.
     */
    public int getStatus( LogRecord record );

    /**
     * 요청에 따른 처리시간을 ms단위로 반환한다.
     * @param record a LogRecord
     * @return processing time. 만약 올바른 값을 얻지 못할 경우 -1을 반환한다.
     */
    public long getProcessingTimeMillis( LogRecord record );
}          

사용자가 Access log의 특정 패턴에 대해 필터링하는 경우 위의 AccessLoggerFilter 인터페이스 및 AbstractAccessLoggerFilter 추상 클래스를 이용하여 쉽게 필터를 구현해서 적용할 수 있다.

사용자의 필터 클래스는 jeus.servlet.util.AbstractAccessLoggerFilter를 상속하고, java.util.logging.Filter의 isLoggable() 메소드를 구현해야 한다. isLoggable() 메소드를 구현할 때 위의 jeus.servlet.util.AccessLoggerFilter의 API 중에서 사용자가 필요한 정보를 적절히 선택하여 이용 및 구현한다.

다음은 요청 확장자가 gif인 경우에만 해당 요청을 Access log로 기록하는 사용자 필터 클래스를 정의한 예이다.

package sample;

import jeus.servlet.util.AbstractAccessLoggerFilter;
import java.util.logging.*;

 public class SimpleAccessLoggerFilter extends AbstractAccessLoggerFilter {
     public boolean isLoggable( LogRecord record ) {
         // get the request uri
         String requestURI = getRequestURI(record );

         // allow only "gif" extension
         return requestURI != null && requestURI.endsWith( "gif" );
     }
 }          
  • sample.SimpleAccessLoggerFilter는 사용자가 정의한 클래스이며 jeus.servlet.util.AbstractAccessLoggerFilter를 한다.

  • java.util.logging.Filter#isLoggable() 메소드를 구현하였으며, 클라이언트의 요청 URI를 얻기 위하여 jeus.servlet.util.AccessLoggerFilter#getRequestURI() API를 이용한다.

  • 해당 클래스를 컴파일한 후 jar 파일 형태로 lib\application 디렉터리에 포함한다.

  • WEBMain.xml의 <access-log> 설정에 해당 필터를 등록한다.

다음은 WEBMain.xml의 <access-log> 설정에 해당 필터를 등록하는 예이다.

[예 2.6] <access-log>에 필터 등록 : <<WEBMain.xml>>

<?xml version="1.0"?>
<web-container xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
    <context-group>
    . . .
        <logging>
            . . .
            <access-log>
                <enable>true</enable>
                . . .                
                <filter-class>
                    sample.SimpleAccessLoggerFilter
                </filter-class>                
                <handler>
                    <file-handler>
                        <name>fileHandler</name>
                        <valid-hour>1</valid-hour>
                    </file-handler>
                </handler>
            </access-log>
        </logging>
    </context-group>
    . . .
</web-container>


2.4.3. User log 관련 설정 항목

User log에만 해당하는 별도의 하위 요소는 없다. User log는 다음에 별도로 설명할 Context DD에서 설정하여 특정 Context 단독으로 사용하는 것이 가능하다. 그러한 경우에는 Context DD 내의 <user-log> 설정이 우선순위를 갖는다.

2.5. 웹 컨테이너 제어와 모니터링

본 절에서는 웹 컨테이너 제어와 모니터링하는 방법에 대해서 설명한다.

2.5.1. 웹 컨테이너 제어

웹 컨테이너를 제어한다는 것은 웹 컨테이너의 시작과 종료를 제어한다는 의미와 같다. 이 2가지 작업은 WebAdmin콘솔 툴(jeusadmin)을 사용해서 제어한다.

본 절에서는 웹 컨테이너에 대한 정보만 포함하며 Context Group과 Context(Web application)에 대해서는 언급하지 않는다.

콘솔 툴(jeusadmin)을 이용한 웹 컨테이너 제어

다음은 jeusadmin을 이용해서 웹 컨테이너 제어하는 예이다. 'johan_servlet_engine1'라는 웹 컨테이너가 JEUSMain.xml과 WEBMain.xml에 설정되어 있다고 가정한다.

  • jeusadmin 시작

    jeusadmin을 시작하고 JEUS 노드에 연결한다.

    C:\> jeusadmin johan

    사용자와 패스워드를 입력하면 jeusadmin 명령창이 나타난다.

  • 노드 시작

    JEUS 노드가 시작되어 있지 않으면 다음의 명령을 실행한다.

    johan> boot

    설정된 웹 컨테이너와 모든 다른 엔진들이 자동으로 시작된다.

  • 노드 종료

    하나의 엔진을 시작하거나 종료하기 위해서는 해당 컨테이너를 시작하거나 종료해야 한다. 따라서 'johan_container' 컨테이너의 'johan_servlet_engine1'이라는 웹 컨테이너가 시작되었다고 가정하고 다음의 명령으로 종료한다.

    johan> downcon johan_container1 
  • 웹 컨테이너 시작

    종료된 웹 컨테이너를 시작하려면 다음의 명령을 실행한다.

    johan> startcon johan_container1 

위의 예에서는 웹 컨테이너에 관련된 명령을 몇 가지 알아보았다. 자세한 내용은 "JEUS Server 안내서"를 참고한다.

WebAdmin을 이용한 웹 컨테이너 제어

WebAdmin을 이용한 웹 컨테이너 제어에 대한 자세한 설명은 "JEUS WebAdmin 안내서"의 Servlet Engine 제어 부분을 참고한다.

2.5.2. 웹 컨테이너 모니터링

모니터링은 특정 웹 컨테이너의 수행하는 경우 데이터와 상황 정보를 수집하는 것을 의미한다.

주의

웹 컨테이너를 모니터링하기 위해서는 콘솔 툴 보다는 상세하고 완전한 엔진 상태 정보를 제공하는 WebAdmin의 사용을 권장한다.

콘솔 툴(jeusadmin)을 통한 웹 컨테이너 모니터링

jeusadmin에서는 웹 컨테이너에 대한 기초 정보를 얻을 수 있는 기능을 제공한다. 자세한 내용은 "JEUS Server 안내서"JEUS Reference Book”의 “4.2.5. 서블릿 엔진 관련 명령어”를 참고한다.

WebAdmin을 통한 웹 컨테이너 모니터링

WebAdmin을 통하여 웹 컨테이너를 모니터링할 수 있다. WebAdmin의 엔진 컨테이너 통계 부분과 Session 서버 통계 부분을 이용한다.