Spring Boot 支持哪些嵌入 Web 容器?
- 标签:Spring Boot、后端
🏛 业务架构师
Spring Boot 支持三种内嵌容器:
- Tomcat(默认):最成熟、生态最广,历史包袱也最多;
- Jetty:轻量、启动快,长连接场景(WebSocket 老项目)有积累;
- Undertow:高并发下内存占用和性能表现优秀。
切换方式是排除默认再引入对应 starter(spring-boot-starter-jetty/undertow)。
业务架构师视角,我的选型逻辑是**"默认不动,理由充分才换"**:
- 绝大多数业务系统:保留 Tomcat。它的稳定性记录、社区资料量、与监控/诊断工具的兼容都最优,团队熟悉度本身就是运维资产。没有量化瓶颈就换容器,属于无收益的差异化;
- 换的真实场景:内存极度敏感(大量小 Pod 部署,Undertow 省下的堆是真实成本);连接数异常高的推送类服务;或公司统一技术栈决策;
- 比选容器更值得投入的是容器参数治理:
server.tomcat.threads.max(默认 200)、max-connections(默认 8192)、accept-count——这些参数与业务峰值 QPS、依赖 RT 的匹配度,直接决定大促时的表现。我见过太多团队纠结容器选型,却让默认 200 工作线程扛着秒杀流量。
另外注意 JDK 21+ 虚拟线程(spring.threads.virtual.enabled=true)大幅改变了线程模型——2026 年这个开关的收益可能远大于换容器。
🏗 系统架构师
可选清单:Tomcat(默认)、Jetty、Undertow(Servlet 栈);Netty(WebFlux/Reactive 栈,Spring Cloud Gateway 基于它)。切换即换依赖:排除 web starter 的 tomcat,引入 jetty/undertow 对应 starter。
选型逻辑(我的对比):
- Tomcat:默认、生态最全、排障资料最多——没有特殊理由不换;
- Undertow:内存占用低,少量线程支撑大量连接,适合高连接数与资源敏感部署;
- Jetty:轻量,嵌入式与 WebSocket/长连接场景友好;
- Netty:非 Servlet 场景(网关、推送、RPC 传输层)的事实标准。
运维参数才是重点:threads.max(默认 200)、max-connections(8191)、accept-count(100)要与下游容量联动推导,不是拍脑袋调大——容器线程打满的下一个受害者一定是数据库连接池。K8s 里还要配 graceful shutdown 与 preStop 摘流,保证滚动发布不丢在途请求。
💻 全栈开发专家
Servlet 栈:Tomcat(默认)、Jetty、Undertow;Reactive 栈:Netty(默认) + Tomcat/Jetty/Undertow。
切换 Jetty 的标准操作:把 starter-web 里的 tomcat 排掉,再引 jetty:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>选型经验:默认 Tomcat 生态最熟、资料最多;追求长连接和低内存选 Undertow;Jetty 多为老项目延续。调优三件套(默认值要背):
yaml
server:
tomcat:
threads:
max: 200 # 工作线程
max-connections: 8192
accept-count: 100K8s 实践必配两件事:优雅停机 server.shutdown: graceful + spring.lifecycle.timeout-per-shutdown-phase: 30s(配合 preStop sleep 让 LB 摘流量);探针分离用 Actuator 的 liveness/readiness,避免慢启动被误杀引发重启风暴。开虚拟线程后 threads.max 语义弱化,瓶颈转移到下游连接池。