1. 개요

Tomcat의 HTTP Thread Pool과 AJP Thread Pool에 대해 설명한다.


2. HTTP Thread Pool

  • Tomcat 버전 : 7.0.70 (2016-06-20 Release)
  • Tomcat 설정 : 기본 설정

아래는 Tomcat을 기동하고 아무 행위를 하지 않았을 때 Thread Pool의 수치가 어떻게 변화하는지 확인하는 실험이다.

시간 내용 Thread 수
10:11:29 기동 시작  
10:11:29 Initializing ProtocolHandler ["http-bio-8080"]  
10:11:30 Initializing ProtocolHandler ["ajp-bio-8009"]  
10:11:31 Dump #0 - HTTP Thread Pool (http-bio-8080-exec-) 0개
10:11:34 Server startup in 4350 ms  
10:11:35 Dump #1 - HTTP Thread Pool (http-bio-8080-exec-) 0개
10:11:38 Dump #2 - HTTP Thread Pool (http-bio-8080-exec-) 3개
10:11:41 Dump #3 - HTTP Thread Pool (http-bio-8080-exec-) 3개
10:11:45 Dump #4 - HTTP Thread Pool (http-bio-8080-exec-) 3개
10:11:48 Dump #5 - HTTP Thread Pool (http-bio-8080-exec-) 3개
10:11:52 Dump #6 - HTTP Thread Pool (http-bio-8080-exec-) 3개
10:11:55 Dump #7 - HTTP Thread Pool (http-bio-8080-exec-) 3개
10:11:58 Dump #8 - HTTP Thread Pool (http-bio-8080-exec-) 3개
10:12:02 Dump #9 - HTTP Thread Pool (http-bio-8080-exec-) 3개
10:12:05 Dump #10 - HTTP Thread Pool (http-bio-8080-exec-) 3개
10:12:09 Dump #11 - HTTP Thread Pool (http-bio-8080-exec-) 6개
10:12:12 Dump #12 - HTTP Thread Pool (http-bio-8080-exec-) 6개
10:12:15 Dump #13 - HTTP Thread Pool (http-bio-8080-exec-) 6개
10:12:19 Dump #14 - HTTP Thread Pool (http-bio-8080-exec-) 6개
10:12:22 Dump #15 - HTTP Thread Pool (http-bio-8080-exec-) 6개
10:12:26 Dump #16 - HTTP Thread Pool (http-bio-8080-exec-) 6개
10:12:29 Dump #17 - HTTP Thread Pool (http-bio-8080-exec-) 6개
10:12:33 Dump #18 - HTTP Thread Pool (http-bio-8080-exec-) 6개
10:12:36 Dump #19 - HTTP Thread Pool (http-bio-8080-exec-) 6개
10:12:39 Dump #20 - HTTP Thread Pool (http-bio-8080-exec-) 9개
10:12:43 Dump #21 - HTTP Thread Pool (http-bio-8080-exec-) 9개
10:12:46 Dump #22 - HTTP Thread Pool (http-bio-8080-exec-) 9개
10:12:50 Dump #23 - HTTP Thread Pool (http-bio-8080-exec-) 9개
10:12:53 Dump #24 - HTTP Thread Pool (http-bio-8080-exec-) 9개
10:12:57 Dump #25 - HTTP Thread Pool (http-bio-8080-exec-) 9개
10:13:00 Dump #26 - HTTP Thread Pool (http-bio-8080-exec-) 9개
10:13:03 Dump #27 - HTTP Thread Pool (http-bio-8080-exec-) 9개
10:13:07 Dump #28 - HTTP Thread Pool (http-bio-8080-exec-) 10개
10:13:10 Dump #29 - HTTP Thread Pool (http-bio-8080-exec-) 10개
10:13:14 Dump #30 - HTTP Thread Pool (http-bio-8080-exec-) 10개
10:13:17 Dump #31 - HTTP Thread Pool (http-bio-8080-exec-) 10개
10:13:20 Dump #32 - HTTP Thread Pool (http-bio-8080-exec-) 10개
10:13:24 Dump #33 - HTTP Thread Pool (http-bio-8080-exec-) 10개
10:13:27 Dump #34 - HTTP Thread Pool (http-bio-8080-exec-) 10개
10:13:31 Dump #35 - HTTP Thread Pool (http-bio-8080-exec-) 10개
10:13:34 Dump #36 - HTTP Thread Pool (http-bio-8080-exec-) 10개

3. AJP Thread Pool

3-1. Tomcat 기동 후 Startup 완료, 아직 요청 없는 상태 

<http-apr-8180-exec-일련번호>와 같은 Worker Thread가 하나도 존재하지 않는다.

3-2. 최초 요청 유입

요청 하나 당 <http-apr-8180-exec-1>과 같은 Worker Thread가 1개 생성된다.

3-3. 동시 Thread 처리

동시 요청량에 따라 <http-apr-8180-exec-일련번호> Thread들이 생성된다.

3-4. 모든 요청 종료 후 Thread Idle 상태 유지 시

각 Thread 별로 Idle 60초 후 Thread drop되며, 총 Idle Thread가 minSpareThreads(기본 10) 값에 도달할 경우 더이상 Thread drop되지 않는다.

3-5. 

중요한 것은 60초. http Connector 설정 중 connectionTimeout이나 keepAliveTimeout이 20000(20초)이든 90000(90초)이든 요청 처리 후 무조건 Idle 60초 후에 Thread drop된다. AbstractEndpoint 클래스를 확인해보자.

    public void createExecutor() {
        internalExecutor = true;
        TaskQueue taskqueue = new TaskQueue();
        TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
        executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
        taskqueue.setParent( (ThreadPoolExecutor) executor);
    }

그리고 ThreadPoolExecutor의 생성자이다.

    public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, new RejectHandler());
    }

위와 같이 keepAliveTime이 60초로 고정되어 있음을 확인할 수 있다.


4. 요약

  1. 기동 후 실 요청이 들어오지 않으면 AJP Worker Thread는 0개이다. (단, AsyncTimeout, Acceptor, Poller Thread 등 제외)
  2. 별도로 keepAliveTimeout를 설정하지 않으면 connectionTimeout과 동일한 값으로 설정된다고 가이드되어 있으나, 위와 같이 확인한 결과 60초로 강제 설정되고 있다. (단, Executor가 아닌 개별 Connector 사용 시)
  3. keepAliveTimeout을 90000(ms, =90초) 등 명시적으로 설정하더라도 역시 60초 keepAliveTImeout이 적용된다.