Sunday, January 3, 2010

Tomcat thread pool don't shrink as you expect it to be

Assume if this is your current tomcat's web thread pool configuration,

<executor name="webThreadPool" nameprefix="web-" maxthreads="100" minsparethreads="10"></executor>

Based on the above configuration, 0 threads will be created after the tomcat startup, depending on the number of concurrent requests number of threads will be created in the thread pool, for instance if there are 5 concurrent requests then 5 threads will be created in the pool and these threads are further reused by subsequent requests until more concurrent requests come where further threads will be created. Because of the minSpareThreads value of 10 all the threads created up to 10 will not be discarded irrespective of whether the threads are idle or not. Thread pools shrink based on the maxIdleTime which by default is 60000 ms/ 60 secs / 1 minute meaning if a thread is idle for 60 secs tomcat will discard it from the pool.Suppose there is a spike in the number of concurrent requests say 50 then about 50 threads will be created in the pool to accommodate the spike. if your average is 1 request/sec except during the spike you would expect the threadpool to shrink after the spike, but unfortunately this is not how tomcat does. Tomcat uses the logic in such a way that the threads are picked and used in a round-robin manner from the pool, since you are getting about a average of 1 requests/sec the thread pool won't shrink since all the 50 existing threads in the pool will be used at least once within a minute when there are 1 requests/sec coming. Ideally, I would expect tomcat to reuse the same free/idle thread (Most Recently Used thread) as much as possible instead of the round-robin policy to be able to discard the idle thread. Since it's not working as expected the only way to control is to reduce the maxIdle time with an optimal value, but reducing the maxIdle time also possess some risks. This also becomes an inconvenience if your monitoring system is alerting based on the number of thread pool count, in such cases using activeCount value of the thread pool is a wise thing to avoid false alerts.

<executor name="webThreadPool" nameprefix="web-" maxthreads="400" minsparethreads="10" maxidletime="3000"></executor>