简单说:默认配置下,单实例 SpringBoot 大约能同时处理 200 个请求 ,排队最多再加 100 个;调优后常规可到 500--2000 ,异步/虚拟线程架构可达 数万 。下面从原理、配置、代码实测到优化,一次性讲清楚。

一、核心:请求处理靠「内嵌容器线程池」
SpringBoot 本身不直接处理 HTTP 请求,而是依赖内嵌的 Servlet 容器(默认是 Tomcat,也可换 Jetty/Undertow)。
1.1 默认线程池参数(Tomcat)
yaml
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 准备测试接口(模拟业务延迟)
java
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class ConcurrencyController {
/**
* 模拟业务接口:处理耗时 500ms
*/
@GetMapping("/test")
public String test(@RequestParam(defaultValue = "500") long delay) throws InterruptedException {
String threadName = Thread.currentThread().getName();
log.info("请求开始,线程:{}", threadName);
// 模拟业务处理(数据库查询/接口调用)
Thread.sleep(delay);
log.info("请求结束,线程:{}", threadName);
return "OK - " + threadName;
}
}
3.2 配置文件(application.yml)
yaml
server:
tomcat:
threads:
max: 200 # 默认最大线程
min-spare: 10
accept-count: 100
max-connections: 8192
# 日志级别(方便观察线程)
logging:
level:
root: INFO
com.example: INFO
3.3 压测结果(JMeter/ab)
- 并发 200:全部正常响应,无排队。
- 并发 250:200 个处理中,50 个排队。
- 并发 300:200 处理 + 100 排队。
- 并发 301+ :直接返回
Connection refused。
四、如何调高并发能力?(3 种方案)
方案 1:调大 Tomcat 线程池(简单直接)
yaml
server:
tomcat:
threads:
max: 800 # 调大最大线程(4核8G建议500-800)
min-spare: 50
accept-count: 500 # 增大排队长度
max-connections: 10000
适用:同步业务、CPU 充足场景。
方案 2:异步化(@Async + 线程池)
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
public class AsyncConfig {
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(50);
executor.setMaxPoolSize(200);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
java
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class BizService {
@Async
public void asyncProcess() throws InterruptedException {
// 耗时操作(不阻塞主线程)
Thread.sleep(500);
}
}
适用:可异步化的后台任务、非核心流程。
方案 3:WebFlux 非阻塞(高并发 IO 场景)
java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
public class WebFluxController {
@GetMapping("/flux")
public Mono<String> fluxTest() {
// 非阻塞延迟(不占线程)
return Mono.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/虚拟线程 ,单机可达 数万。
- 终极方案 :水平扩展 + 负载均衡(多实例部署,突破单机限制)。