스레드 풀

본 장에서는 JEUS 웹 엔진에서 사용하는 스레드 풀의 구성 요소와 기본적인 설정 방법에 대해 설명한다.

1. 개요

웹 엔진에서 요청을 처리하기 위해서는 스레드 풀이 필수적이다.

스레드 풀은 Web-Connection, VirtualHost, Context 단에서 설정할 수 있으며, 우선순위가 존재하여 요청에 따라 각각 다른 스레드 풀에서 처리될 수 있다.

우선 3개의 스레드 풀을 다 활용하기 위해서는 Selector 기반으로 돌아가야 하며, 서버 리스너 설정이 있는 Ajp, Http, Tcp 리스너와 use-nio가 true인 WebtoB 커넥터가 이에 해당한다. use-nio가 false인 WebtoB 커넥터와 Tmax 커넥터는 오직 웹 커넥션 레벨의 스레드 풀에서만 처리된다.

Context와 VirtualHost 레벨에서의 스레드 풀은 선택사항이고, Web-Connection 레벨의 스레드 풀은 필수적으로 설정해야 한다. Context 스레드 풀은 jeus-web-dd.xml에서 설정이 가능하고, VirtualHost와 Web-Connection 스레드 풀은 domain.xml에서 각각 <virtual-host>와 <web-connections> 하위에서 설정이 가능하다.

[참고] JEUS 21 이전에는 Web Connection 별로 스레드 풀이 존재했었고, JEUS 21 FIX 0에서는 서버 리스너가 있는 Ajp, Http, Tcp 웹 커넥션은 WebContainer, VirtualHost, Context 레벨의 스레드 풀에서 처리될 수 있었고, WebtoB와 Tmax 커넥터는 자신에게 종속하는 스레드 풀에서 처리되었다.

2. 기본 구조

본 절에서는 WebContainer, VirtualHost, Context의 레벨의 스레드 풀 생성, 소멸 시점과 역할을 설명한다.

Web-Connection 레벨의 스레드 풀은 웹 엔진이 기동될 때 설정된 Web-Connection을 생성하거나 동적으로 Web-Connection을 추가할 때 생성되며, 조건에 맞는 Context와 VirtualHost의 스레드 풀이 없을 때 디폴트로 요청을 처리하는 스레드 풀이다. Web-Connection이 제거될 때 같이 스레드 풀도 소멸된다.

VirtualHost 레벨의 스레드 풀은 웹 엔진이 기동될 때 설정된 VirtualHost를 생성하거나 동적으로 VirtualHost를 추가할 때, 스레드 풀에 대한 설정이 존재하면 각 VirtualHost마다 스레드 풀을 생성한다. 참고로, System application을 위한 System Host와, 디폴트로 설정되는 Default Host는 스레드 풀을 생성하지 않는다. VirtualHost를 제거할 때 해당하는 스레드 풀이 소멸된다.

Context 레벨의 스레드 풀은 application이 deploy될 때 스레드 풀에 대한 설정이 존재하면 스레드 풀을 생성한다. Context 레벨의 스레드 풀은 다른 레벨의 스레드 풀과 달리 하나 이상의 스레드 풀을 설정할 수 있다. Context 레벨의 스레드 풀은 하나의 base 스레드 풀과 하나 이상의 Service Group 스레드 풀을 설정할 수 있다. Service Group 스레드 풀은 특정 uri로 온 요청들을 처리하기 위해 하나 이상의 uri를 ','로 구분하여 uri들을 설정할 수 있으며, 요청이 많이 들어올 리소스를 효율적으로 처리할 수 있도록 도와준다. uri에 매칭되는 Service Group 스레드 풀이 없을 경우에 base 스레드 풀이 설정되어 있다면, Service Group에 설정된 uri를 제외한 모든 요청들은 base 스레드 풀로 처리된다. 만약 base 스레드 풀도 설정되어 있지 않다면, VirtualHost 또는 디폴트인 Web-Connection 레벨의 스레드 풀로 요청을 처리한다. application이 undeploy될 때 생성된 모든 스레드 풀이 소멸된다.

3. 설정

본 절에서는 각 레벨의 스레드 풀 설정 방법을 설명한다.

Web-Connection 레벨의 스레드 풀은 domain.xml에 정의되어야 한다. 만약 설정하지 않는다면, JEUS 기동에 실패하게 된다.

Web-Connection 레벨의 스레드 풀 : <domain.xml>
<web-connections>
    <http-listener>
        <thread-pool>
            <min>10</min>
            <max>40</max>
            <max-idle-time>300000</max-idle-time>
            <max-queue>30</max-queue>
        </thread-pool>
    </http-listener>
</web-connections>

위의 예제에 나온 것 같이 Web-Connection 레벨의 스레드 풀은 <Web-Connections> 하위에 설정된 각 리스너 혹은 커넥터마다 하나의 스레드 풀을 설정할 수 있다. 선택된 Context와 VirtualHost 레벨의 스레드 풀이 없을 경우에 요청을 처리한다.

또한 jeusadmin에서 동적으로 추가할 때도 스레드 풀을 필수적으로 설정해야 하며, 자세한 것은 콘솔 툴을 사용한 ajp-listener 추가를 참고한다.

VirtualHost 레벨의 스레드 풀은 domain.xml에 정의되어야 한다. 선택적으로 설정할 수 있으며, 설정하지 않을 경우에는 Web-Connection 레벨의 스레드 풀에서 처리된다.

VirtualHost 레벨의 스레드 풀 : <domain.xml>
<web-engine>
    <virtual-host>
        <virtual-host-name>testHost</virtual-host-name>
        <host-name>192.1.1.1</host-name>
        <thread-pool>
            <min>10</min>
            <max>20</max>
            <max-idle-time>300000</max-idle-time>
            <max-queue>30</max-queue>
        </thread-pool>
    </virtual-host>
</web-engin>

위의 예제에 나온 것 같이 VirtualHost 레벨의 스레드 풀은 <virtual-host> 하위에 하나의 스레드 풀을 설정할 수 있다. 선택된 Context 레벨의 스레드 풀이 없을 경우에 요청을 처리하고, VirtualHost 레벨의 스레드 풀을 설정하지 않으면 Web-Connection 레벨의 스레드 풀로 넘긴다.

또한 jeusadmin에서 동적으로 추가할 때도 스레드 풀을 설정할 수 있으며, 자세한 것은 가상 호소트 설정을 참고한다.

Context 레벨의 스레드 풀은 jeus-web-dd.xml에 정의되어야 한다. 선택적으로 설정할 수 있으며, 설정하지 않을 경우에는 VirtualHost 레벨의 스레드 풀에서 처리된다.

Context 레벨의 스레드 풀 : <jeus-web-dd.xml>
<jeus-web-dd>
    <thread-pool>
        <base>
            <name>baseThreadPool</name>
            <min>30</min>
            <max>50</max>
            <max-idle-time>300000</max-idle-time>
            <max-queue>30</max-queue>
        </base>
        <service-group>
            <name>service1</name>
            <uri>/index.html,/index.jsp</uri>
            <min>10</min>
            <max>20</max>
            <max-idle-time>300000</max-idle-time>
            <max-queue>30</max-queue>
        </service-group>
        <service-group>
            <name>service2</name>
            <uri>/mostRequestedResource</uri>
            <min>10</min>
            <max>20</max>
            <max-idle-time>300000</max-idle-time>
            <max-queue>30</max-queue>
        </service-group>
    </thread-pool>
</jeus-web-dd>

위의 예제에 나온 것 같이 Context 레벨의 스레드 풀은 <jeus-web-dd> 하위에 하나의 base 스레드 풀과 하나 이상의 service-group 스레드 풀을 설정할 수 있다. 다수의 Context 스레드 풀을 구분하기 위해서 unique한 name을 지정해주어야 한다. 요청된 uri가 service-group에 설정된 uri와 매칭된다면 해당 service-group의 스레드 풀로 요청을 처리하고, 없을 경우에는 base 스레드 풀로 처리한다. base 스레드 풀이 설정되지 않았다면, VirtualHost 레벨의 스레드 풀로 넘긴다.

또한 jeusadmin에서 deploy할 때에도 단 하나의 Context 스레드 풀을 추가적으로 넣어줄 수가 있다. 자세한 것은 JEUS Reference 안내서의 deploy-application을 참고한다.

  • Thread Pool 공통 설정

    • Worker Thread Pool에 대한 설정이다.

    • 다음은 세부 사항을 설정하는 하위 항목에 대한 설명이다.

      항목 설명

      Min

      Pool에서 관리할 최소 Worker Thread의 개수이다.

      Max

      Pool에서 관리할 최대 Worker Thread의 개수이다.

      Maximum Idle Time

      Pool 내에 존재하던 Thread가 제거되기 전까지의 사용되고 있지 않은 시간을 지정한다.

      Max Queue

      Queue에 대기할 수 있는 요청의 최대 개수를 설정한다.

      Thread State Notify

      블록되는 Worker Thread가 발생될 경우 이를 알려준다.

      각 Thread Pool은 장애가 발생했을 때 취하는 액션을 정의하는 'Thread State Notify' 항목을 가지고 있다. 이것에 대해서는 자동 Thread Pool 관리 설정(Thread 상태 통보)을 참고한다.

4. 자동 Thread Pool 관리 설정(Thread 상태 통보)

Thread 상태 통보는 이메일 통지나 서버 재시작 권고를 위해 필요한 최소의 Worker Thread 수와 관련된 오류 조건을 정의한다.

다음은 콘솔에서 Thread 상태 통보를 설정하는 과정에 대한 설명이다. 설정이 완료되면 Thread Pool의 Thread 상태 변경에 대한 통보 설정을 통해 원하는 통보를 받을 수 있다.

자동 Thread Pool 관리 설정이 되면 'Max Thread Active Time' 설정값을 기준으로 Worker Thread가 관리된다. 요청을 받아 처리를 시작한 시점부터 Max Thread Active 설정 시간을 초과한 Thread들은 Blocked Thread로 관리가 된다. 그리고 Blocked Thread가 아닌 일반 Thread들의 숫자가 Thread Pool에서 설정한 최솟값보다 작을 경우는 새로운 Worker Thread를 생성하여 최솟값을 유지할 수 있게 한다.

이메일 알림자를 사용할 경우 이메일 알림자를 통해 받을 이메일의 설정은 JEUS Server 안내서의 로깅 설정에서 "SMTP 핸들러" 항목을 참고한다.

<web-engine>
    <web-connections>
        <http-listener>
            <thread-pool>
                ...
                <thread-state-notify>
                    <max-thread-active-time>10000</max-thread-active-time>
                    <interrupt-thread>false</interrupt-thread>
                    <active-timeout-notification>false</active-timeout-notification>
                    <notify-threshold-ratio>0.1</notify-threshold-ratio>
                    <notify-subject>Notify-Subject</notify-subject>
                    <restart-threshold-ratio>0.1</restart-threshold-ratio>
                    <restart-subject>Restart-Subject</restart-subject>
                </thread-state-notify>
            </thread-pool>
        </http-listener>
    </web-connections>
</web-engine>

다음은 각 항목에 대한 설명이다.

항목 설명

Max Thread Active Time

블록되기 전까지 Worker Thread가 사용될 수 있는 최대시간을 설정한다.

이 시간은 Worker Thread가 클라이언트 요청을 서비스할 때부터 측정된다(서블릿이 수행될 때). 설정한 시간이 초과되었거나 또는 Thread가 자유롭게 되어 Thread Pool로 되돌아 갈 때 만료된다(Thread가 block되지 않는 상황). 설정값이 0이거나 음수이면 무시된다.

Notify Threshold Ratio

존재할 수 있는 Blocked Thread의 최대 비율을 설정한다. 전체 Thread 개수 대비 Blocked Thread의 비율이 초과되면, 오류 조건으로 결정되어 이메일 알림자를 통하여 이메일 통보가 전송된다.

1보다 작은 소숫점으로 설정하며, 0이거나 음수이면 무시된다.

Restart Threshold Ratio

존재할 수 있는 Blocked Thread의 최대 비율을 설정한다. 전체 Thread 개수 대비 Blocked Thread의 비율이 초과되면, 오류 조건으로 결정되어 이메일 알림자를 통하여 이메일 통보가 전송된다. 그 후에 서버 로그에 서버 재시작 권고 메시지가 기록된다.

1보다 작은 소숫점으로 설정하며, 0이거나 음수이면 이 설정이 무시된다.

Notify Subject

경고 이메일을 전송할 때 사용된다.

Restart Subject

엔진 로그 및 통보할 때 사용하는 이메일에 사용된다.

Interrupt Thread

Active Timeout이 발생할 때, 즉 Worker Thread가 'Max Thread Active Time' 설정값 이상으로 요청을 처리 중일 때 해당 Thread의 interrupt 발생 유무를 결정한다.

  • true : interrupt를 발생시킨다.

  • false : interrupt를 발생시키지 않는다. (기본값)

Active Timeout Notification

Active Timeout 발생이 이메일 전송 여부를 결정한다.

  • true : 이메일을 전송한다.

  • false : 이메일을 전송하지 않는다. (기본값)

이메일을 받기 위해 SMTP 핸들러를 설정할 로거는 이름을 "jeus.servlet.threadpool.notify"로 하여 따로 추가하길 권장한다.

5. 규칙

스레드 풀을 구성할 때 적용되는 규칙은 다음과 같다.

  • Context, VirtualHost 레벨의 스레드 풀을 사용하기 위해서는 스레드 풀로 작업을 넘기기 전에 요청을 읽고 Context와 Host를 판단할 수 있어야 한다.

    이에 해당하는 Web-Connections는 서버 리스너가 설정 가능한 Http, Ajp13, Tcp 리스너와 use-nio가 true인 WebtoB 커넥터이다. use-nio가 false인 WebtoB 커넥터와 Tmax 커넥터는 Web-Connection 스레드풀만 사용한다.

  • WebtoB 설정할 때 주의점

    WebtoB 커넥터는 use-nio에 설정에 따라 스레드 풀 설정에 주의해야 한다. use-nio가 true인 경우에는 connection 갯수와 스레드 사이에는 더 이상 아무 관련이 없기 때문에, 튜닝에 맞게 적절한 값을 넣으면 되지만, use-nio가 false인 경우에는 WebtoB 커넥터의 Connection-Count와 thread-pool의 min, max 값이 동일해야 한다. 동일하지 않을 경우에는 서버 기동에 실패하게 된다.

  • Service Group 스레드 풀을 설정할 때 똑같은 uri를 서로 다른 Service Group에 정의하지 않도록 주의해야 한다. uri는 '/'로 시작해야 하며, 서블릿 표준에서 Context path 다음으로 오는 Servlet path와 path Info에 해당한다.

  • uri를 정의할 때는 하위의 경로도 포함할 수 있다는 것을 고려해야 한다. 예를 들어 Service Group의 uri에 "/myServlet/"으로 지정하였다면, /testContext/myServlet/servlet1과 /testContext/myServlet/servlet2 요청 모두 "/myServlet/"으로 설정한 Service Group으로 처리한다.

  • 다수의 Service Group이 정의되어 있을 때는 가장 많이 매칭되는 uri를 선택하도록 한다.

    예를 들어, Service Group1의 uri에 "/myServlet/"으로 지정하였고, Service Group2의 uri에 "/myServlet/servlet2"으로 지정하였다면, /testContext/myServlet/servlet1 요청은 Service Group1로 /testContext/myServlet/servlet2 요청은 Service Group2로 처리한다.

  • 요청을 어떤 스레드 풀로 처리될지 선택하는 과정은 간단하다.

    1. 요청이 들어온 Web-Connection이 Context와 VirtualHost 스레드 풀을 사용할 수 있는지 판단한다. 해당 스레드풀을 사용할 수 없는 Web-Connection이라면 Web-Connection 스레드 풀로 처리한다.

    2. 요청에 해당하는 Context가 스레드 풀들을 가지고 있는지 확인한다. Service Group 스레드 풀이 설정되어 있다면, uri를 비교해서 맞으면 해당 스레드 풀로 처리하고, 아니면 다음 스레드 풀을 찾는다.

    3. Context 스레드 풀에 base 스레드 풀이 설정되어 있다면 base 스레드 풀로 처리한다.

    4. 요청에 해당하는 Virtual Host에 스레드 풀이 설정되 있다면 해당 스레드풀로 처리한다.

    5. 4번까지 해당하는 스레드 풀이 없다면 Web-Connection 스레드 풀로 요청을 처리한다.