1. Springboot Tomcat 架构及参数优化
1.1. 版本说明
构件 | 版本 |
---|
spring-boot | 2.7.18 |
tomcat-embed-core | 9.0.83 |
1.2. SpringBoot Tomcat 架构分析
1.2.1. Tomcat 核心组件类图
classDiagram
direction LR
class Tomcat {
#Server server
+void start()
+void stop()
}
class Connector {
#ProtocolHandler protocolHandler
}
class Container {
<<Interface>>
}
class Engine {
<<Interface>>
}
class StandardEngine
class Host {
<<Interface>>
}
class StandardHost
class Lifecycle {
<<Interface>>
void start()
void stop()
}
class Server {
<<Interface>>
}
class StandardServer {
-Service[] services
}
class Service {
<<Interface>>
}
class StandardService {
#Connector[] connectors
-Engine engine
}
class AbstractHttp11JsseProtocol~S~
class AbstractHttp11Protocol~S~
class AbstractProtocol~S~ {
-AbstractEndpoint endpoint
}
class Http11NioProtocol
class Http11Nio2Protocol
class ProtocolHandler {
<<Interface>>
void start()
void stop()
}
class AbstractEndpoint~S, U~ {
-Executor executor
-LimitLatch connectionLimitLatch
-Handler~S~ handler
+void bind()
#U serverSocketAccept()
+void createExecutor()
+boolean processSocket(SocketWrapperBase~S~> socketWrapper, SocketEvent event, boolean dispatch)
+void start()
+void stop()
}
class AbstractJsseEndpoint~S, U~
class Nio2Endpoint
class NioEndpoint {
-ServerSocketChannel serverSock
}
class Executor {
<<Interface>>
}
class ThreadPoolExecutor
class VirtualThreadExecutor
class LimitLatch {
-AtomicLong count
-long limit
+long countDown()
+void countUpOrAwait()
}
class Handler {
<<Interface>>
}
class ConnectionHandler~S~
class Poller
class Acceptor
class SocketProcessor
class SocketProcessorBase~S~
class Runnable {
<<Interface>>
}
Tomcat "1" *--> "1" Host
Tomcat "1" *--> "1" Server
Host --|> Container
StandardHost ..|> Host
StandardServer ..|> Server
StandardServer "1" *--> "n" Service
Server --|> Lifecycle
Service --|> Lifecycle
StandardService ..|> Service
StandardService "1" *--> "1" Engine
StandardService "1" *--> "n" Connector
StandardEngine ..|> Engine
Engine --|> Container
Container --|> Lifecycle
Connector ..|> Lifecycle
Connector "1" *--> "1" ProtocolHandler
Http11NioProtocol --|> AbstractHttp11JsseProtocol
Http11Nio2Protocol --|> AbstractHttp11JsseProtocol
AbstractHttp11JsseProtocol --|> AbstractHttp11Protocol
AbstractHttp11Protocol --|> AbstractProtocol
AbstractProtocol ..|> ProtocolHandler
AbstractProtocol "1" *--> "1" AbstractEndpoint
AbstractJsseEndpoint --|> AbstractEndpoint
Nio2Endpoint --|> AbstractJsseEndpoint
NioEndpoint --|> AbstractJsseEndpoint
AbstractEndpoint "1" *--> "1" Executor
AbstractEndpoint "1" *--> "1" LimitLatch
AbstractEndpoint "1" *--> "1" Handler
AbstractEndpoint ..> SocketProcessorBase
ThreadPoolExecutor ..|> Executor
VirtualThreadExecutor ..|> Executor
ConnectionHandler ..|> Handler
Poller ..|> Runnable
Acceptor ..|> Runnable
Poller ..> AbstractEndpoint
Acceptor ..> AbstractEndpoint
SocketProcessor --|> SocketProcessorBase~S~
SocketProcessorBase~S~ ..|> Runnable
- Tomcat 线程池在 AbstractEndpoint 创建,server.tomcat.threads.max、server.tomcat.threads.min-spare 参数作用于此,用于指定最大、最小线程数,线程池其他参数默认值为:是否守护线程:是;线程优先级:5;空闲线程存活时间:60 秒;任务队列为:TaskQueue,容量为 Integer.MAX_VALUE
- LimitLatch 用于限制连接数量,基于 AQS 实现,server.tomcat.max-connections 参数作用于此,接受一个连接前判断是否达到最大连接数 limit,否则自旋等待直至成功并 count 加 1;关闭连接后 count 减 1
- Poller 线程不停从已连接的 socket 读取事件,最终封装成 SocketProcessorBase 交给 ThreadPoolExecutor 处理
- Acceptor 线程不停接收新的客户端连接,直至达到 server.tomcat.max-connections
- SocketProcessorBase 线程将请求经过层层传递最终给到DispatcherServlet,DispatcherServlet 再分派到对应的Spring Controller 中处理具体的业务逻辑
1.2.2. Tomcat 核心组件架构图

1.3. SpringBoot Tomcat 工作流程
1.3.1. SpringBoot 初始化 Tomcat 流程
flowchart TD
flow1("SpringApplication#run(Class<?> primarySource, String... args)") --> flow2("SpringApplication#run(Class<?>[] primarySources, String[] args)")
flow2 --> flow3("SpringApplication#run(String... args)")
flow3 --> flow4("SpringApplication#refreshContext(ConfigurableApplicationContext context)")
flow4 --> flow5("SpringApplication#refresh(ConfigurableApplicationContext applicationContext)")
flow5 --> flow6("ServletWebServerApplicationContext#refresh()")
flow6 --> flow7("AbstractApplicationContext#refresh()")
flow7 --> flow8("ServletWebServerApplicationContext#onRefresh()")
flow8 --> flow9("ServletWebServerApplicationContext#createWebServer()")
subgraph flow10["TomcatServletWebServerFactory#getWebServer(ServletContextInitializer... initializers)"]
direction LR
flow10_1("Tomcat#Tomcat()")
flow10_1 --> flow10_2("Tomcat#start()")
end
flow9 --> flow10
1.3.2. Tomcat 启动流程
flowchart TD
flow1["Tomcat#start()"]
flow2["StandardServer#start()"]
flow3["StandardService#start()"]
flow4["StandardEngine#start()"]
flow5["Connector#start()"]
flow6["Http11NioProtocol#start()"]
subgraph flow7["NioEndpoint#start()"]
flow8["NioEndpoint#bind() \n 初始化 ServerSocketChannel,绑定端口"]
flow9["NioEndpoint#createExecutor() \n 创建工作线程池"]
flow10["NioEndpoint#initializeConnectionLatch() \n 初始化限流组件"]
flow11["Poller#Poller() \n 启动 socket 事件监听线程"]
flow12["Acceptor#Acceptor() \n 启动 socket 连接线程"]
end
flow1 --> flow2
flow2 --> flow3
flow3 --> flow4
flow3 --> flow5
flow5 --> flow6
flow6 --> flow7
flow7 --> flow8
flow8 --> flow9
flow9 --> flow10
flow10 --> flow11
flow11 --> flow12
1.3.2.1. 初始化 ServerSocketChannel
核心源码:
serverSock = ServerSocketChannel.open();
InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset());
serverSock.bind(addr, getAcceptCount());
- 打开 ServerSocketChannel。
- 绑定端口,指定 backlog
其中端口由 server.port
配置参数指定,backlog 由 server.tomcat.accept-count
配置参数指定,默认值为 100,客户端与服务端完成 TCP 三次握手之后,连接放入等待队列中,ServerSocketChannel 调用 accept() 方法从队列中取出连接。因此,当 Tomcat 达到 max-connections
指定的最大连接数后,还能继续接收 accept-count
数量的连接。
1.3.2.2. 初始化工作线程池
核心源码:
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);
TaskQueue
任务队列继承自 LinkedBlockingQueue
,这里无法指定容量,默认容量为 Integer.MAX_VALUE
,即无限大。预计未来将支持指定容量,详见 github issues。TaskThreadFactory
线程工厂指定了线程名称前缀为 http-nio-端口-
;线程为守护线程;线程优先级为默认值:5。- 线程池核心线程数由
server.tomcat.threads.min-spare
配置参数指定,默认值为 10;线程池最大线程数由 server.tomcat.threads.max
配置参数指定,默认值为 200;空闲线程存活时间 60 秒。
TaskQueue
重写了 offer
方法,使得 Tomcat 线程池与 JDK 线程池创建线程的时机不一样,具体表现为:
- 如果线程池里的线程数量等于最大线程数,说明无法再创建新线程,任务加入队列中,等待空闲线程处理。
- 如果已提交的任务数小于等于线程池里的线程数量,说明有空闲线程,任务加入队列中,由空闲线程处理。
- 如果线程池里的线程数量小于最大线程数,任务无法加入队列,强制线程池新建线程去处理。
- 如果以上都不是,任务加入队列,等待空闲线程处理。
核心源码:
@Override
public boolean offer(Runnable o) {
//we can't do any checks
if (parent==null) {
return super.offer(o);
}
//we are maxed out on threads, simply queue the object
if (parent.getPoolSizeNoLock() == parent.getMaximumPoolSize()) {
return super.offer(o);
}
//we have idle threads, just add it to the queue
if (parent.getSubmittedCount() <= parent.getPoolSizeNoLock()) {
return super.offer(o);
}
//if we have less threads than maximum force creation of a new thread
if (parent.getPoolSizeNoLock() < parent.getMaximumPoolSize()) {
return false;
}
//if we reached here, we need to add it to the queue
return super.offer(o);
}
1.3.2.3. 初始化限流组件 LimitLatch
核心源码:
protected LimitLatch initializeConnectionLatch() {
if (maxConnections==-1) {
return null;
}
if (connectionLimitLatch==null) {
connectionLimitLatch = new LimitLatch(getMaxConnections());
}
return connectionLimitLatch;
}
最大连接数由 server.tomcat.max-connections
配置参数指定,默认值为 8192,表示同一时间 Tomcat 能够接受的最大连接数量。接受一个新连接 LimitLatch 计数加 1,处理完请求断开连接,LimitLatch 计数减 1。
1.3.3. Acceptor 线程工作流程
flowchart TD
flow1["线程启动"]
flow2{"停止?"}
flow3["尝试 LimitLatch 计数加 1"]
flow4{"成功?"}
flow6["SocketChannel socket = endpoint.serverSocketAccept() \n 接收新连接"]
flow7["SocketChannel 封装为 NioSocketWrapper"]
flow8["NioSocketWrapper 封装为 PollerEvent"]
flow9["PollerEvent 注册到 Poller 的 SynchronizedQueue 队列,Poller 线程处理队列里的事件"]
flow1 --> flow2
flow2 --> |no|flow3
flow3 --> flow4
flow4 --> |no \n 自旋-等待-重试|flow3
flow4 --> |yes|flow6
flow6 --> flow7
flow7 --> flow8
flow8 --> flow9
flow9 --> flow2
1.3.4. Poller 线程工作流程
flowchart TD
flow1["线程启动"]
flow2{"while(true)"}
flow3["Poller#events() \n 处理 SynchronizedQueue 队列里的 PollerEvent 事件"]
flow4["Selector#selectedKeys() \n 监听 socket 事件"]
flow5["Poller#processKey(SelectionKey sk, NioSocketWrapper socketWrapper) \n 处理监听到的事件"]
flow6["AbstractEndpoint#processSocket(SocketWrapperBase socketWrapper, SocketEvent event, boolean dispatch) \n 封装 SocketProcessor 多线程任务,提交到线程池处理"]
flow1 --> flow2
flow2 --> |yes|flow3
flow3 --> flow4
flow4 --> flow5
flow5 --> flow6
flow6 --> flow2
SocketProcessor 线程处理请求工作流程
flowchart TD
flow1["SocketProcessor#doRun()"]
flow2["ConnectionHandler#process(SocketWrapperBase socket, SocketEvent status)"]
flow3["Http11Processor#process(SocketWrapperBase socketWrapper, SocketEvent status)"]
flow4["CoyoteAdapter#service(Request req, Response res)"]
subgraph subgraph1["Connector"]
subgraph subgraph1_1["Service"]
subgraph subgraph1_1_1["Engine"]
subgraph subgraph1_1_1_1["Pipeline"]
flow5["StandardEngineValve#invoke(Request request, Response response)"]
end
end
end
end
subgraph subgraph2["Host"]
subgraph subgraph 2_1["Pipeline"]
flow6["StandardHostValve#invoke(Request request, Response response)"]
end
end
subgraph subgraph3["Context"]
subgraph subgraph 3_1["Pipeline"]
flow7["StandardContextValve#invoke(Request request, Response response)"]
end
end
subgraph subgraph4["Wrapper"]
subgraph subgraph 4_1["Pipeline"]
flow8["StandardWrapperValve#invoke(Request request, Response response)"]
end
end
flow9["FilterChain#doFilter(ServletRequest request, ServletResponse response)"]
flow10["DispatcherServlet#service(ServletRequest req, ServletResponse res)"]
flow11["RequestMappingHandlerAdapter#handle(HttpServletRequest request, HttpServletResponse response, Object handler)"]
flow12["ServletInvocableHandlerMethod#(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs)"]
flow13["Controller 层,处理具体业务"]
flow1 -->|NioSocketWrapper| flow2
flow2 -->|NioSocketWrapper| flow3
flow3 -->|Request, Response| flow4
flow4 -->|Request, Response| flow5
flow5 -->|Request, Response| flow6
flow6 -->|Request, Response| flow7
flow7 -->|Request, Response| flow8
flow8 -->|ServletRequest, ServletResponse| flow9
flow9 -->|ServletRequest, ServletResponse| flow10
flow10 -->|ServletRequest, ServletResponse, HandlerMethod| flow11
flow11 --> flow12
flow12 --> flow13
1.4. 配置参数优化
服务器配置:
server:
tomcat:
threads:
max: 1000
min-spare: 200
accept-count: 1000
max-connections: 10000
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。