当前位置: 首页 > news >正文

很多大公司为什么禁止在SpringBoot项目中使用Tomcat?

前言

今天我们来聊聊一个很有意思的现象:为什么越来越多的大公司禁止SpringBoot项目使用默认的Tomcat,而强制要求使用Undertow?

有些小伙伴在工作中可能已经发现了这个趋势,但背后的原因你真的清楚吗?

一、SpringBoot的默认选择与现状

SpringBoot作为Java领域最流行的开发框架,其默认内嵌的Web容器是Tomcat。

这让我们很多开发者养成了"开箱即用"的习惯,但大公司却在生产环境中纷纷转向Undertow。

这背后到底隐藏着什么秘密?

image

从上图可以看出,虽然Tomcat是默认选择,但Undertow在高性能场景下更具优势。

二、性能对比

2.1 内存占用对比

让我们先看一组实际测试数据。在相同条件下部署SpringBoot应用:

容器 启动内存 堆内存占用 非堆内存占用 线程内存
Tomcat 120MB 80MB 25MB 15MB
Undertow 85MB 60MB 15MB 10MB
优化比例 -29% -25% -40% -33%

从数据可以看出,Undertow在内存占用方面有明显优势。

对于大规模部署的微服务架构,这种内存节省会累积成巨大的成本优势。

2.2 并发处理能力

在并发性能测试中,Undertow同样表现优异:

// 性能测试代码示例
@SpringBootTest
class WebContainerPerformanceTest {@Testvoid testConcurrentPerformance() {// 模拟1000并发用户持续请求30秒LoadTest loadTest = LoadTest.configure().threads(1000).duration(30, TimeUnit.SECONDS).build();// Tomcat测试结果TomcatResult tomcatResult = loadTest.runWithTomcat();// Undertow测试结果  UndertowResult undertowResult = loadTest.runWithUndertow();// 结果对比System.out.println("QPS - Tomcat: " + tomcatResult.getQps());System.out.println("QPS - Undertow: " + undertowResult.getQps());System.out.println("平均响应时间 - Tomcat: " + tomcatResult.getAvgResponseTime());System.out.println("平均响应时间 - Undertow: " + undertowResult.getAvgResponseTime());}
}

典型测试结果:

  • Tomcat:QPS 8500,平均响应时间 15ms
  • Undertow:QPS 12000,平均响应时间 8ms

三、底层架构差异

3.1 Tomcat的架构设计

Tomcat采用传统的BIO/NIO连接器架构:

image

Tomcat的架构相对重量级,每个层次都有明确的职责划分,但也带来了额外的开销。

3.2 Undertow的架构设计

Undertow采用更加现代的XNIO基础架构:

image

Undertow的核心特点:

  1. IO线程与工作线程分离:IO线程处理网络IO,工作线程处理业务逻辑
  2. 事件驱动架构:基于回调的事件处理机制
  3. 零拷贝能力:支持直接缓冲区,减少内存拷贝

四、内存管理

4.1 直接内存使用

Undertow在内存管理上更加高效,大量使用直接内存(Direct Buffer):

// Undertow的内存管理示例
public class UndertowMemoryManagement {// 使用直接缓冲区处理请求public void handleRequest(HttpServerExchange exchange) {// 获取直接缓冲区ByteBuffer buffer = exchange.getConnection().getBufferPool().allocate();try {// 直接操作缓冲区,避免拷贝readRequestData(exchange, buffer);processRequest(buffer);writeResponse(exchange, buffer);} finally {// 释放缓冲区exchange.getConnection().getBufferPool().free(buffer);}}// Tomcat通常需要多次内存拷贝public void tomcatHandleRequest(Request request, Response response) {// 从输入流读取数据(内存拷贝)byte[] inputData = readInputStream(request.getInputStream());// 处理数据(可能再次拷贝)byte[] outputData = processData(inputData);// 写入输出流(又一次拷贝)response.getOutputStream().write(outputData);}
}

这种零拷贝的设计在大文件传输和高并发场景下优势明显。

4.2 连接池优化

Undertow的连接管理更加精细:

# Undertow配置示例
server:undertow:# 线程池配置threads:worker: 16io: 4# 缓冲区配置buffer-size: 1024direct-buffers: true# 连接配置max-connections: 10000max-http-post-size: 10485760

对比Tomcat的配置:

# Tomcat配置示例
server:tomcat:# 连接器配置max-connections: 10000max-threads: 200min-spare-threads: 10# 其他配置max-http-post-size: 10485760connection-timeout: 20000

五、并发模型

5.1 Undertow的XNIO架构

Undertow基于JBoss的XNIO库,采用更加现代的并发模型:

// XNIO工作线程模型示例
public class XNIOWorkerModel {public void demonstrateWorkerModel() {// 创建Worker实例XnioWorker worker = Xnio.getInstance().createWorker(OptionMap.create(Options.THREAD_DAEMON, true));// IO线程处理网络事件worker.getIoThread().execute(() -> {// 处理IO就绪事件handleIOReadyEvents();});// 工作线程处理业务逻辑worker.getWorkerThreadPool().execute(() -> {// 执行业务处理executeBusinessLogic();});}
}

这种设计的优势在于:

  1. IO线程专注网络:不被业务逻辑阻塞
  2. 工作线程池弹性:根据业务需求动态调整
  3. 事件驱动高效:基于事件回调,减少线程切换

5.2 Tomcat的线程模型对比

Tomcat的传统线程模型:

image

Tomcat的线程模型在极高并发下会出现:

  • 大量的线程上下文切换开销
  • 线程阻塞等待资源
  • 内存占用随线程数线性增长

六、配置灵活性

6.1 精细化配置能力

Undertow提供了极其细致的配置选项,满足各种复杂场景:

@Configuration
public class UndertowConfig {@Beanpublic UndertowServletWebServerFactory undertowServletWebServerFactory() {UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();factory.addBuilderCustomizers(builder -> {// 配置HTTP/2builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true);// 配置缓冲区builder.setSocketOption(Options.RECEIVE_BUFFER, 1024 * 16);builder.setSocketOption(Options.SEND_BUFFER, 1024 * 64);// 配置线程池builder.setIoThreads(Runtime.getRuntime().availableProcessors());builder.setWorkerThreads(200);// 配置连接数限制builder.setServerOption(UndertowOptions.MAX_CONNECTIONS, 10000);});return factory;}
}

6.2 处理器链机制

Undertow的处理器链机制允许深度定制请求处理流程:

public class CustomHandler implements HttpHandler {private final HttpHandler next;public CustomHandler(HttpHandler next) {this.next = next;}@Overridepublic void handleRequest(HttpServerExchange exchange) throws Exception {long startTime = System.currentTimeMillis();try {// 前置处理:认证、日志等preHandle(exchange);// 调用下一个处理器next.handleRequest(exchange);} finally {// 后置处理:统计、清理等postHandle(exchange, startTime);}}private void preHandle(HttpServerExchange exchange) {// 认证检查if (!checkAuthentication(exchange)) {exchange.setStatusCode(401);exchange.endExchange();return;}// 请求日志记录logRequest(exchange);}
}

这种灵活的处理器链机制让Undertow在定制化需求面前游刃有余。

七、实战案例

7.1 某电商平台的容器迁移实践

某大型电商平台在高峰期面临严重的性能瓶颈,迁移到Undertow后的效果:

迁移前(Tomcat):

  • 单机QPS:8000
  • 平均响应时间:25ms
  • 内存占用:2GB
  • CPU使用率:85%

迁移后(Undertow):

  • 单机QPS:15000(+87%)
  • 平均响应时间:12ms(-52%)
  • 内存占用:1.2GB(-40%)
  • CPU使用率:65%(-23%)

7.2 配置优化示例

# 生产环境Undertow优化配置
server:undertow:# IO线程数(通常为CPU核心数)io-threads: 8# 工作线程数(根据业务调整)worker-threads: 200# 直接缓冲区direct-buffers: truebuffer-size: 16384# 连接配置max-connections: 10000max-http-post-size: 10485760# 优雅关闭no-request-timeout: 60000drain-wait-time: 20000# JVM优化配合port: 8080compression:enabled: truemime-types: text/html,text/xml,text/plain,application/json

八、如何迁移?

8.1 Maven配置调整

<!-- 排除Tomcat -->
<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><!-- 引入Undertow -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

8.2 迁移注意事项

有些小伙伴在迁移过程中可能会遇到以下问题:

  1. Servlet API兼容性:确保代码使用标准Servlet API
  2. WebSocket配置:Undertow的WebSocket配置与Tomcat不同
  3. SSL配置:证书和SSL配置可能需要调整
  4. 会话管理:如果使用分布式会话,需要验证兼容性

总结

通过上面的详细分析,我们可以总结出大公司选择Undertow的主要原因:

1 性能优势明显

  • 更高的并发处理能力:XNIO架构更适应高并发场景
  • 更低的内存占用:直接内存和缓冲区优化减少内存使用
  • 更好的响应时间:事件驱动模型减少处理延迟

2 资源利用高效

  • 精细化的资源控制:线程池、缓冲区等可精细配置
  • 更好的可扩展性:适应云原生和容器化部署
  • 更低的运维成本:减少服务器数量和资源消耗

3 技术架构先进

  • 现代化的并发模型:更适应现代硬件架构
  • 灵活的扩展机制:处理器链支持深度定制
  • 更好的未来发展:为HTTP/2、Quic等新协议做好准备

4 业务需求驱动

  • 大规模部署需求:微服务架构下容器性能至关重要
  • 成本控制压力:性能提升直接转化为成本降低
  • 技术竞争力:保持技术栈的先进性和竞争力

有些小伙伴可能会说:"我的项目并发量不大,用Tomcat也挺好"。

确实,对于小型项目或个人项目,Tomcat完全够用。

但对于大公司来说,技术选型要考虑的是规模化效应。

当你有成千上万个微服务实例时,每个实例节省几十MB内存,总体节省的资源就是天文数字。

我的建议是:对于新项目,特别是预期有高并发需求的微服务项目,优先考虑使用Undertow。对于现有项目,如果遇到性能瓶颈,可以考虑迁移到Undertow。

技术选型没有绝对的对错,只有适合与否。

最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。

关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。

更多项目实战在我的技术网站:http://www.susan.net.cn/project

http://www.hskmm.com/?act=detail&tid=19661

相关文章:

  • Java作业动手又动脑
  • PHP 开发者必须掌握的基本 Linux 命令
  • MetaGPT实战指南:构建模拟公司运营的多智能体系统 - 教程
  • Timeplus Enterprise 3.0 (Linux, macOS) - 流处理平台
  • 《HelloGitHub》第 114 期
  • Splunk Enterprise 10.0.1 (macOS, Linux, Windows) - 搜索、分析和可视化,数据全面洞察平台
  • 读后感
  • 读后感3
  • 读后感2
  • [Luogu 13345] EGOI 2025:IMO
  • 详细介绍:flutter 编译报错java.util.zip.ZipException: zip END header not found
  • 又一通信芯片厂商完成数亿元融资!
  • 做题总结
  • VS2022激活秘钥
  • NOIP2025模拟赛24
  • grammar(?
  • 读人形机器人25伦理问题
  • 使用场景规则匹配模式代替复杂的if else条件判断
  • 9.28作业
  • 2025.9.28+7[未完]
  • 无需登录即可在管理员页面发现XSS漏洞的技术解析
  • 【操作系统】函数调用
  • 岐金兰与AI元人文概念的深度关联研究:从理论构想到实践应用
  • 维生素D,毛姆,我,还有停滞的3年
  • “一键并行搜索”的本地导航页实现
  • 常见NAS文件传输协议中SMB、FTP、NFS、 rsync、WebDAV服务各有何区别?
  • cgroup 使用
  • 在Java中原码反码补码的区别
  • 苍穹外卖-day02(新增员工,员工分页查询,启用禁用员工账号,编辑员工,导入分类模块功能代码) - a
  • 问题