针对tomcat、jetty、undertow的详细对比,并结合spring boot的实际使用说明
1. 基本概述
| 特性 | tomcat | jetty | undertow |
|---|---|---|---|
| 开发方 | apache 基金会 | eclipse 基金会 | red hat(jboss/wildfly 子项目) |
| 定位 | 传统 servlet 容器 | 轻量级嵌入式服务器 | 高性能非阻塞服务器 |
| 核心协议 | http/1.1, 支持 http/2(需配置) | http/1.1, http/2, websocket | http/1.1, http/2, websocket |
| 主要应用场景 | 企业级 web 应用(如 spring mvc) | 微服务、嵌入式系统(如 spring boot) | 高并发 api、实时通信(如 websocket) |
2. 架构与性能
| 维度 | tomcat | jetty | undertow |
|---|---|---|---|
| 架构模型 | 传统线程池(bio/nio可选) | 基于 nio 的非阻塞模型 | 基于 xnio 的事件驱动非阻塞模型 |
| 性能特点 | 高稳定性,中等并发能力 | 高并发处理,低延迟 | 极致性能,高吞吐量,低内存占用 |
| 资源消耗 | 较高(默认配置较保守) | 较低(轻量级设计) | 极低(优化内存管理) |
| 典型性能场景 | 500-1000 并发(默认配置) | 5000-10000 并发连接 | 10000+ 并发连接 |
3. 功能与生态
| 功能 | tomcat | jetty | undertow |
|---|---|---|---|
| servlet 支持 | 完整支持(servlet 6.0+) | 完整支持(servlet 6.0+) | 完整支持(servlet 6.0+) |
| http/2 | 需手动配置(alpn 支持复杂) | 原生支持 | 原生支持 |
| websocket | 支持(需额外配置) | 原生支持 | 原生支持 |
| 模块化设计 | 无(功能集中) | 支持(按需加载模块) | 轻量级核心(扩展性强) |
| 嵌入式部署 | 支持(但较重) | 极佳(spring boot 默认替代选项) | 极佳(spring boot 可选集成) |
4. 配置与易用性
| 维度 | tomcat | jetty | undertow |
|---|---|---|---|
| 配置方式 | xml 文件,图形化管理工具(如 manager) | 代码/xml,强调 api 配置 | 代码/编程式配置(灵活性高) |
| 学习曲线 | 低(文档丰富,社区成熟) | 中(需理解 nio 模型) | 较高(需熟悉 xnio 事件模型) |
| 默认优化 | 保守(适合传统应用) | 较激进(适合现代架构) | 高度优化(性能优先) |
| 日志管理 | 完善(与 log4j 等集成) | 灵活(可定制日志组件) | 简洁(需手动配置扩展) |
5. 核心对比
| 维度 | tomcat | jetty | undertow |
|---|---|---|---|
| spring boot 默认支持 | ✅ 默认嵌入式容器(spring-boot-starter-web) | ❌ 需手动配置(替换 tomcat) | ❌ 需手动配置(替换 tomcat) |
| 启动速度 | 中等 | 较快 | 极快 |
| 内存占用 | 较高 | 较低 | 最低 |
| 并发能力 | 中等(bio/nio 模型) | 高(nio 非阻塞) | 极高(xnio 事件驱动) |
| 适用场景 | 传统 web 应用、jsp 项目 | 微服务、嵌入式设备 | 高并发 api、websocket 实时通信 |
6. 适用场景建议
选择 tomcat:
- 需要稳定性和广泛兼容性的传统企业应用。
- 使用 jsp 或旧版 java ee 技术的项目。
- 对运维友好,需要图形化管理工具的场景。
选择 jetty:
- 微服务架构或嵌入式应用(如 iot 设备)。
- spring boot 项目希望替换默认容器以降低资源消耗。
- 需要快速启动和低内存占用的场景。
选择 undertow:
- 高并发 api 服务或实时通信(如 websocket 聊天室)。
- 对性能极致追求,需低延迟和高吞吐量的系统。
- 与 wildfly 或其他 red hat 技术栈集成。
7. 性能对比数据参考
内存占用(空载):
- tomcat: ~120mb
- jetty: ~50mb
- undertow: ~30mb
响应时间(10k 并发):
- tomcat: ~200ms
- jetty: ~150ms
- undertow: ~100ms
吞吐量(qps):
- tomcat: 5k-8k
- jetty: 10k-15k
- undertow: 20k-30k+
8. 在 spring boot 中使用
(1) tomcat(默认容器)
依赖配置:无需额外配置,spring-boot-starter-web 默认包含 tomcat。
<!-- maven -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>自定义配置:
# application.yml
server:
port: 8080
tomcat:
max-threads: 200 # 最大线程数(默认 200)
min-spare-threads: 10 # 最小空闲线程数
connection-timeout: 5000(2) jetty
依赖配置:需排除 tomcat 并添加 jetty 依赖。
<!-- maven -->
<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>自定义配置:
# application.yml
server:
port: 8080
jetty:
thread-pool:
max-threads: 500 # jetty 默认线程池配置
min-threads: 10(3) undertow
依赖配置:排除 tomcat 并添加 undertow 依赖。
<!-- maven -->
<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-undertow</artifactid>
</dependency>自定义配置:
# application.yml
server:
port: 8080
undertow:
threads:
io: 4 # i/o 线程数(默认 cpu 核心数 * 2)
worker: 40 # 工作线程数(默认 io * 8)
buffer-size: 1024 # 缓冲区大小(字节)9. 性能调优建议
tomcat
- 优化线程池:调整
max-threads和min-spare-threads。 - 开启 nio 模式(默认已启用):
server:
tomcat:
protocol: org.apache.coyote.http11.http11nioprotocoljetty
异步处理:利用 jetty 的异步 servlet 特性提升吞吐量。
调整 selector 线程:
@bean
public jettyservletwebserverfactory jettyservletwebserverfactory() {
jettyservletwebserverfactory factory = new jettyservletwebserverfactory();
factory.addservercustomizers(server -> {
queuedthreadpool threadpool = server.getbean(queuedthreadpool.class);
threadpool.setmaxthreads(500);
});
return factory;
}
undertow
优化 xnio 工作线程:根据 cpu 核心数动态调整 io 和 worker 线程。
启用直接内存缓冲:
server:
undertow:
direct-buffers: true # 使用堆外内存提升性能10. 适用场景与选择建议
| 场景 | 推荐容器 | 理由 |
|---|---|---|
| 传统企业应用 | tomcat | 兼容性强,支持 jsp 和旧版 java ee 规范。 |
| 微服务/云原生应用 | jetty | 轻量级、启动快,适合资源受限的 docker 容器或 kubernetes 环境。 |
| 高并发 api/websocket | undertow | 极致性能,内存占用低,适合实时通信和高吞吐场景(如 im、游戏服务器)。 |
11. 常见问题
q1:如何在 spring boot 中动态切换容器?
- 通过 maven/gradle 的依赖排除和引入实现,无需修改代码。
q2:undertow 是否支持 servlet 3.1+?
- ✅ 完全支持 servlet 4.0、websocket 和 http/2。
q3:jetty 和 undertow 对 websocket 的支持?
- 两者均原生支持 websocket,无需额外配置。
12. 总结
- tomcat:适合稳定性优先的传统项目,文档和生态完善。
- jetty:平衡性能与轻量级,适合微服务和嵌入式场景。
- undertow:性能王者,适合高并发、实时通信需求、低延迟的现代应用。
选择建议:根据项目需求权衡性能、资源消耗和开发体验。微服务或云原生场景可优先考虑 jetty 或 undertow;传统企业应用 tomcat 仍是稳妥选择。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论