Understanding Tomcat Connectors: NIO, BIO, APR, Thread Pools and Configuration Parameters
This article explains Tomcat's Connector architecture, compares BIO, NIO and APR protocols, details key parameters such as acceptCount, maxConnections, maxThreads, and shows how to configure and monitor thread pools and connection limits for optimal server performance.
Preface
When using Tomcat, configuration issues related to connection numbers and thread counts are common; to truly understand these concepts, one must first grasp Tomcat's Connector, which receives connection requests, creates Request and Response objects, and delegates processing to the Engine via threads.
The Connector is the backbone of Tomcat's request handling, and its configuration directly impacts performance. This article focuses on the Connector, discussing important topics such as NIO/BIO modes, thread pools, and connection limits.
1. NIO, BIO, APR
1.1 Connector protocol
Tomcat supports different protocols for handling HTTP requests. Older versions support BIO, NIO, and APR; Tomcat 8 adds NIO2, while Tomcat 8.5/9 drop BIO support.
BIO is blocking I/O, NIO is non‑blocking I/O, and APR (Apache Portable Runtime) leverages native libraries for high scalability and performance, requiring apr, apr‑utils, and tomcat‑native packages.
1.2 How to specify protocol
The protocol is set via the protocol attribute of the <Connector> element, or defaults are used.
Typical values are:
HTTP/1.1 – default, version‑dependent
org.apache.coyote.http11.Http11Protocol – BIO
org.apache.coyote.http11.Http11NioProtocol – NIO
org.apache.coyote.http11.Http11Nio2Protocol – NIO2
org.apache.coyote.http11.Http11AprProtocol – APR
If omitted, Tomcat selects a default based on the version (e.g., BIO or APR for Tomcat 7, NIO or APR for Tomcat 8).
1.3 Differences between BIO and NIO
Both BIO and NIO follow the same high‑level flow: accept connections, read request data, create Request objects, invoke the servlet container, and return a Response.
In BIO, the main entity is JIoEndpoint with an Acceptor and a Worker thread pool; the Acceptor blocks when no worker is free.
In NIO, the main entity is NIoEndpoint , which adds a Poller that registers sockets with a Selector, allowing non‑blocking reads before handing work to Worker threads. This non‑blocking step greatly improves concurrency under high load.
2. Three key parameters: acceptCount, maxConnections, maxThreads
2.1 acceptCount
Length of the accept queue; when the queue reaches this size, additional connections are rejected. Default is 100.
2.2 maxConnections
Maximum number of simultaneous connections Tomcat will handle. If the limit is reached, the Acceptor stops reading new connections. A value of –1 means unlimited. Defaults vary by protocol (NIO 10000, APR 8192, BIO maxThreads).
2.3 maxThreads
Maximum number of request‑processing threads. Default is 200. This number is usually much larger than the CPU core count because many threads spend most of their time blocked (e.g., waiting for I/O), allowing higher CPU utilization.
2.4 Parameter tuning
• maxThreads should be larger than the number of CPU cores but not excessively high to avoid thread‑switch overhead. • For BIO, set maxConnections equal to maxThreads; for NIO, set maxConnections much larger than maxThreads. • acceptCount should reflect the desired behavior under overload: too large leads to long wait times, too small causes immediate connection refusals.
3. Thread pool Executor
The <Executor> element defines a shared thread pool that Connectors can reference via the executor attribute.
Typical configuration:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4" />
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" acceptCount="1000" />Key Executor attributes include name, maxThreads, minSpareThreads, maxIdleTime, daemon, threadPriority, and namePrefix.
4. Viewing current status
Server status can be inspected via tools (e.g., JConsole, Tomcat Manager) or Linux commands.
4.1 Connection count
Example (assuming Tomcat listens on port 8083):
netstat -nat | grep 8083The output shows listening sockets, established connections, and those in CLOSE_WAIT.
4.2 Thread count
Use ps -e | grep java to find the Tomcat process ID, then:
ps -o nlwp 27989to see total threads, and:
ps -eLo pid,stat | grep 27989 | grep running | wc -lto count only running threads.
References
Tomcat 7/8/8.5 official documentation, articles on Tomcat thread pool sizing, and various blog posts on BIO/NIO implementations.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.