简单说:默认配置下,单实例 SpringBoot 大约能同时处理 200 个请求,排队最多再加 100 个;调优后常规可到500–2000,异步/虚拟线程架构可达数万。下面从原理、配置、代码实测到优化,一次性讲清楚。
一、核心:请求处理靠「内嵌容器线程池」
SpringBoot 本身不直接处理 HTTP 请求,而是依赖内嵌的 Servlet 容器(默认是Tomcat,也可换 Jetty/Undertow)。
1.1 默认线程池参数(Tomcat)
server:tomcat:threads:max:200# 最大工作线程数(默认200,决定并发上限)min-spare:10# 最小空闲线程数(默认10)max-connections:8192# 最大TCP连接数(默认8192)accept-count:100# 等待队列长度(默认100)- 结论(默认):
- 同时处理:200 个(maxThreads)
- 排队等待:100 个(accept-count)
- 超过 300 个直接拒绝(Connection refused)
1.2 关键概念区分
- maxThreads(线程数):真正能同时干活的「工人」,决定并发处理能力。
- accept-count(队列):排队长度,工人满了后来的人先排队。
- max-connections(连接数):系统能维持的最大 TCP 连接数(通常远大于线程数)。
二、影响并发量的 4 大因素
2.1 硬件资源(物理天花板)
- CPU 核心数:线程要 CPU 调度,4 核服务器实际稳定并发约 200–500,8 核可到 800–2000。
- 内存:每个线程占栈内存(默认 1M),200 线程≈200M,内存不足会 OOM。
- 网络带宽:大文件/高流量场景会先被带宽限制。
2.2 业务逻辑(代码快慢)
- 纯内存计算:10ms/请求 → 200 线程≈2000 QPS。
- 数据库查询:100ms/请求 → 200 线程≈200 QPS(常受数据库连接池瓶颈)。
- 阻塞 IO(调用第三方接口):线程被卡死等待,并发骤降。
2.3 容器配置(可动态调优)
- 调高
maxThreads到 500–800(需配合 CPU/内存)。 - 调高
accept-count到 500(避免高峰期直接拒绝)。
2.4 架构模型(同步 vs 异步)
- Spring MVC(同步阻塞):一线程一请求,上限通常200–2000。
- WebFlux(异步非阻塞):少量 EventLoop 线程可支撑10000+并发(适合高 IO 场景)。
- Java 21+ 虚拟线程:轻量级线程,几乎无栈内存开销,单机可支撑数十万并发。
三、代码实测:默认配置到底能扛多少?
3.1 准备测试接口(模拟业务延迟)
importlombok.extern.slf4j.Slf4j;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;@Slf4j@RestControllerpublicclassConcurrencyController{/** * 模拟业务接口:处理耗时 500ms */@GetMapping("/test")publicStringtest(@RequestParam(defaultValue="500")longdelay)throwsInterruptedException{StringthreadName=Thread.currentThread().getName();log.info("请求开始,线程:{}",threadName);// 模拟业务处理(数据库查询/接口调用)Thread.sleep(delay);log.info("请求结束,线程:{}",threadName);return"OK - "+threadName;}}3.2 配置文件(application.yml)
server:tomcat:threads:max:200# 默认最大线程min-spare:10accept-count:100max-connections:8192# 日志级别(方便观察线程)logging:level:root:INFOcom.example:INFO3.3 压测结果(JMeter/ab)
- 并发 200:全部正常响应,无排队。
- 并发 250:200 个处理中,50 个排队。
- 并发 300:200 处理 + 100 排队。
- 并发 301+:直接返回
Connection refused。
四、如何调高并发能力?(3 种方案)
方案 1:调大 Tomcat 线程池(简单直接)
server:tomcat:threads:max:800# 调大最大线程(4核8G建议500-800)min-spare:50accept-count:500# 增大排队长度max-connections:10000适用:同步业务、CPU 充足场景。
方案 2:异步化(@Async + 线程池)
importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@ConfigurationpublicclassAsyncConfig{@BeanpublicThreadPoolTaskExecutortaskExecutor(){ThreadPoolTaskExecutorexecutor=newThreadPoolTaskExecutor();executor.setCorePoolSize(50);executor.setMaxPoolSize(200);executor.setQueueCapacity(500);executor.setThreadNamePrefix("Async-");executor.initialize();returnexecutor;}}importorg.springframework.scheduling.annotation.Async;importorg.springframework.stereotype.Service;@ServicepublicclassBizService{@AsyncpublicvoidasyncProcess()throwsInterruptedException{// 耗时操作(不阻塞主线程)Thread.sleep(500);}}适用:可异步化的后台任务、非核心流程。
方案 3:WebFlux 非阻塞(高并发 IO 场景)
importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;importreactor.core.publisher.Mono;@RestControllerpublicclassWebFluxController{@GetMapping("/flux")publicMono<String>fluxTest(){// 非阻塞延迟(不占线程)returnMono.delay(java.time.Duration.ofMillis(500)).map(l->"WebFlux OK");}}适用:网关、高 IO、长连接场景,并发可达10000+。
五、常见误区澄清
“max-connections=8192 就是能处理 8192 并发”
❌ 错。max-connections是 TCP 连接数上限,真正并发由maxThreads决定。“线程数越大越好”
❌ 错。线程超过 CPU 核心数过多,会导致频繁上下文切换,反而降性能。“WebFlux 一定比 MVC 快”
❌ 错。CPU 密集型场景(如计算),MVC 可能更快;IO 密集型(如查库/调接口)WebFlux 优势明显。
六、最后总结下哈
- 默认值:单实例≈200 并发处理 + 100 排队。
- 常规调优:
maxThreads=500–800,并发可达500–2000。 - 高并发场景:用WebFlux/虚拟线程,单机可达数万。
- 终极方案:水平扩展 + 负载均衡(多实例部署,突破单机限制)。