前言

作为互联网软件开发人员,你是否在生产环境中遇到过这些痛点:高并发场景下 Tomcat 频繁线程阻塞、微服务部署时容器占用资源过高、WebSocket 长连接出现内存泄漏?Spring Boot3.5 默认集成的 Tomcat 10.1.x 虽成熟稳定,但在复杂业务场景中已逐渐暴露局限性。

从技术选型角度看,替换内置容器的核心价值体现在三点:

性能优化:Undertow 基于 IO 多路复用模型,高并发下 TPS 比 Tomcat 提升 30%-40%,某大厂支付团队压测数据显示,相同配置下 Undertow 峰值 TPS 达 1.2 万,而 Tomcat 仅 8000;

资源节省:Undertow 核心 Jar 包体积仅 1.2MB,比 Tomcat(2.5MB)节省 52%,数百个微服务集群可整体降低 20% 资源成本;

场景适配:Jetty 对 WebSocket 支持更原生,适合即时通讯场景;Netty 则是 Spring WebFlux 响应式编程的最佳搭配,而 Tomcat 在这些场景中易出现兼容性问题。

Spring Boot3.5 的 “可插拔” 设计理念,为容器替换提供了天然支持,这也是互联网团队优化服务性能的主流技术方案之一。

Spring Boot3.5 容器加载的核心机制

在动手替换前,必须先理解底层加载逻辑,避免出现依赖冲突或启动失败。Spring Boot3.5 的内置容器加载本质是 “自动配置 + 依赖传递” 的组合机制:

默认加载逻辑:当引入spring-boot-starter-web依赖时,Maven/Gradle 会自动传递
spring-boot-starter-tomcat,这是 Tomcat 成为默认容器的根本原因。从源码层面,SpringBootWebAutoConfiguration类会扫描 classpath 中的容器工厂类(如 Tomcat 的TomcatServletWebServerFactory、Jetty 的JettyServletWebServerFactory),加载优先级为 Tomcat > Jetty > Undertow;

替换核心思路:通过 “排除 Tomcat 依赖 + 引入目标容器依赖”,改变 classpath 中的容器类优先级,让 Spring Boot 自动识别并加载新容器;

版本兼容性要求:Spring Boot3.5 对容器版本有严格限制 ——Jetty 需搭配 11.x(支持 Jakarta EE 9)、Undertow 需用 2.2.x,手动指定不兼容版本会导致 “类找不到” 错误,建议通过 starter 依赖自动管理版本。

3 大主流容器替换完整步骤(Maven)

前置条件

  • JDK 17+(Spring Boot3.x 最低要求);
  • Spring Boot3.5 版本(本文以最新稳定版为例);
  • 已创建基于spring-boot-starter-web的 Web 项目。

方案 1:替换为 Undertow(高并发首选)

Undertow 以高性能、低资源占用著称,适合秒杀、大促等核心业务场景:

排除 Tomcat 依赖

Maven(pom.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>

引入 Undertow 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

优化配置(application.yml)

server:
  undertow:
    io-threads: 4  # IO线程数,建议设为CPU核心数
    worker-threads: 16  # 工作线程数,默认200,根据业务调整
    buffer-size: 1024  # 缓冲区大小,单位KB
    direct-buffers: true  # 启用直接内存,提升性能

方案 2:替换为 Jetty(轻量级场景)

Jetty 适合中小型微服务、嵌入式设备,对 WebSocket 支持更友好:

排除 Tomcat 依赖(同方案 1 步骤 1);

引入 Jetty 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

核心配置(application.yml)

server:
  jetty:
    acceptors: 2  #  acceptor线程数,处理连接请求
    selectors: 4  #  selector线程数,处理IO事件
    max-http-post-size: 10MB  # 限制POST请求大小

方案 3:替换为 Netty(响应式编程)

若项目使用 Spring WebFlux 响应式架构,Netty 是官方推荐容器:

排除 Tomcat 依赖(同方案 1 步骤 1);

引入 Netty 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-reactor-netty</artifactId>
</dependency>

响应式配置(application.yml)

spring:
  reactor:
    netty:
      http:
        max-keep-alive-time: 30s  # 长连接超时时间
        compression: enabled  # 启用Gzip压缩

总结:容器替换的 6 个关键避坑点

  1. 依赖排除要彻底:除了排除spring-boot-starter-tomcat,还要检查是否有第三方依赖间接引入 Tomcat,可通过mvn dependency:tree命令排查;
  2. 避免版本冲突:不要手动指定容器版本,依赖 Spring Boot starter 的版本管理机制,否则可能导致 Servlet API 不兼容(Spring Boot3.5 对应 Servlet 6.0 规范);
  3. 配置参数适配:IO 线程数建议设为 CPU 核心数(如 4 核 CPU 设为 4),工作线程数根据业务调整,过多线程会导致上下文切换开销增大;
  4. 启动验证:启动后查看日志,确认容器类型(如 Undertow 会输出 “Undertow started on port (s)”),避免替换失败未发现;
  5. 压测对比:替换后需进行压测,重点关注 TPS、响应时间、内存占用,与原 Tomcat 对比,确保达到预期优化效果;
  6. 特殊场景适配:WebSocket 服务优先选 Jetty,响应式编程选 Netty,高并发微服务选 Undertow,常规场景 Tomcat 仍可满足需求。

结语

Spring Boot3.5 的内置容器替换,是互联网软件开发人员提升服务性能的 “低成本高收益” 方案。通过本文的原理剖析和实战步骤,你可根据业务场景选择合适的容器 ——Undertow 主攻高并发、Jetty 主打轻量化、Netty 适配响应式架构。

替换后不仅能降低资源成本,更能提升系统稳定性,尤其在大促、秒杀等核心场景中,容器优化往往能成为 “压垮骆驼的最后一根稻草”。建议收藏本文,在实际项目中按需落地,如有疑问可在评论区交流!

更多推荐