使用 Undertow 替代 Tomcat

使用 Undertow 替代 Tomcat 的优势与配置

为什么要用 Undertow 替代 Tomcat

1. 性能优势

  • 更低的资源占用:Undertow 内存占用比 Tomcat 少 30-50%

  • 更高的并发处理能力:基于 XNIO 的非阻塞 I/O 模型

  • 更好的响应时间:轻量级架构减少处理延迟

2. 架构优势

  • 模块化设计:只加载需要的组件

  • 嵌入式部署:更适合微服务架构

  • 灵活配置:支持编程式配置

详细优势对比

性能指标对比

指标 Tomcat Undertow 优势
内存占用 较高 减少30-50%
启动时间 较慢 减少40-60%
并发连接 10k+ 50k+ 5倍提升
CPU使用率 中等 更高效

技术特性对比

java 复制代码
// Undertow 基于 XNIO 的优势:
// 1. 非阻塞I/O
// 2. 零拷贝技术
// 3. 直接内存访问
// 4. 更精细的线程控制

Spring Boot 中配置 Undertow

1. 添加依赖

XML 复制代码
<!-- 移除 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>

2. 基础配置

java 复制代码
# application.yml
server:
  port: 8080
  undertow:
    # 线程池配置
    threads:
      io: 16
      worker: 256
    # 缓冲区配置
    buffer-size: 1024
    direct-buffers: true
    # HTTP配置
    max-http-post-size: 0
    # 连接配置
    max-connections: 10000

3. 高级配置示例

java 复制代码
@Configuration
public class UndertowConfig {
    
    @Bean
    public UndertowServletWebServerFactory undertowServletWebServerFactory() {
        UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
        
        // 自定义构建器
        factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
            @Override
            public void customize(Builder builder) {
                // 服务器配置
                builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true)
                       .setServerOption(UndertowOptions.HTTP2_SETTINGS_ENABLE_PUSH, true)
                       .setServerOption(UndertowOptions.ALWAYS_SET_KEEP_ALIVE, false)
                       .setServerOption(UndertowOptions.ALWAYS_SET_DATE, true);
                
                // 缓冲区配置
                builder.setBufferSize(1024 * 16)
                       .setIoThreads(Runtime.getRuntime().availableProcessors() * 2)
                       .setWorkerThreads(200);
            }
        });
        
        // 监听器配置
        factory.addDeploymentInfoCustomizers(deploymentInfo -> {
            deploymentInfo.setDefaultEncoding("UTF-8");
            deploymentInfo.setUrlCharset(StandardCharsets.UTF_8.name());
        });
        
        return factory;
    }
}

4. 完整的配置类

java 复制代码
@Configuration
@EnableConfigurationProperties(UndertowProperties.class)
public class AdvancedUndertowConfig {
    
    @Autowired
    private UndertowProperties undertowProperties;
    
    @Bean
    @Primary
    public ServletWebServerFactory servletContainer() {
        UndertowServletWebServerFactory factory = 
            new UndertowServletWebServerFactory();
        
        // 基础配置
        factory.setPort(undertowProperties.getPort());
        factory.setContextPath(undertowProperties.getContextPath());
        
        // 高级自定义配置
        factory.addBuilderCustomizers(this::customizeBuilder);
        factory.addDeploymentInfoCustomizers(this::customizeDeployment);
        
        return factory;
    }
    
    private void customizeBuilder(Builder builder) {
        // XNIO 工作线程配置
        builder.setWorkerThreads(undertowProperties.getWorkerThreads());
        builder.setIoThreads(undertowProperties.getIoThreads());
        
        // 缓冲区配置
        builder.setBufferSize(undertowProperties.getBufferSize());
        builder.setDirectBuffers(undertowProperties.isDirectBuffers());
        
        // 连接配置
        builder.setServerOption(UndertowOptions.MAX_CONNECTIONS, 
                              undertowProperties.getMaxConnections());
        builder.setServerOption(UndertowOptions.MAX_ENTITY_SIZE, 
                              undertowProperties.getMaxEntitySize());
        
        // HTTP/2 配置
        builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true);
        builder.setServerOption(UndertowOptions.HTTP2_SETTINGS_HEADER_TABLE_SIZE, 4096);
        builder.setServerOption(UndertowOptions.HTTP2_SETTINGS_INITIAL_WINDOW_SIZE, 65535);
        
        // 安全配置
        builder.setServerOption(UndertowOptions.RECORD_REQUEST_START_TIME, false);
        builder.setServerOption(UndertowOptions.ALLOW_UNESCAPED_CHARACTERS_IN_URL, true);
    }
    
    private void customizeDeployment(DeploymentInfo deploymentInfo) {
        deploymentInfo.setDefaultEncoding("UTF-8");
        deploymentInfo.setEagerFilterInit(true);
        deploymentInfo.setIgnoreFlush(false);
        
        // Session 配置
        deploymentInfo.setDefaultSessionTimeout(1800);
    }
}

// 配置属性类
@ConfigurationProperties(prefix = "server.undertow")
@Data
public class UndertowProperties {
    private int port = 8080;
    private String contextPath = "";
    private int workerThreads = 256;
    private int ioThreads = Runtime.getRuntime().availableProcessors() * 2;
    private int bufferSize = 1024;
    private boolean directBuffers = true;
    private int maxConnections = 10000;
    private long maxEntitySize = 10485760L; // 10MB
}

5. 性能优化配置

java 复制代码
# application-prod.yml
server:
  undertow:
    threads:
      worker: 500
      io: 32
    buffer-size: 2048
    direct-buffers: true
    max-http-post-size: 104857600  # 100MB
    max-connections: 10000
    no-request-timeout: 60000
    idle-timeout: 30000
    
spring:
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB

6. 监控和健康检查

java 复制代码
@RestController
public class ServerStatusController {
    
    @Autowired
    private XnioWorker xnioWorker;
    
    @GetMapping("/server/status")
    public Map<String, Object> getServerStatus() {
        Map<String, Object> status = new HashMap<>();
        
        // 线程池状态
        status.put("ioThreadCount", xnioWorker.getIoThreadCount());
        status.put("workerThreadCount", xnioWorker.getWorkerThreadCount());
        status.put("busyWorkerThreads", xnioWorker.getBusyWorkerThreadCount());
        
        // 内存状态
        Runtime runtime = Runtime.getRuntime();
        status.put("maxMemory", runtime.maxMemory());
        status.put("totalMemory", runtime.totalMemory());
        status.put("freeMemory", runtime.freeMemory());
        status.put("usedMemory", runtime.totalMemory() - runtime.freeMemory());
        
        return status;
    }
}

迁移注意事项

1. 会话管理

java 复制代码
@Configuration
public class SessionConfig {
    
    @Bean
    public UndertowSessionCustomizer undertowSessionCustomizer() {
        return deploymentInfo -> {
            deploymentInfo.setSessionPersistenceManager(new FileSessionPersistence(
                new File(System.getProperty("java.io.tmpdir"))
            ));
        };
    }
}

2. SSL 配置

java 复制代码
server:
  ssl:
    key-store: classpath:keystore.p12
    key-store-password: changeit
    key-store-type: PKCS12
    key-alias: tomcat
  undertow:
    ssl-contexts:
      default:
        enabled-protocols:
          - TLSv1.2
          - TLSv1.3

总结

使用 Undertow 替代 Tomcat 的主要好处:

  1. 性能提升:更低的延迟,更高的吞吐量

  2. 资源优化:减少内存占用,提高资源利用率

  3. 架构适配:更适合云原生和微服务架构

  4. 配置灵活:支持更细粒度的性能调优

在需要高性能、低延迟的应用场景中,Undertow 是比 Tomcat 更好的选择,特别是在微服务架构和云原生环境中。

相关推荐
无限大624 分钟前
计算机十万个为什么--数据库索引
后端
冬夜戏雪32 分钟前
【java学习日记】【2025.12.7】【7/60】
java·开发语言·学习
CC.GG41 分钟前
【C++】二叉搜索树
java·c++·redis
学历真的很重要1 小时前
VsCode+Roo Code+Gemini 2.5 Pro+Gemini Balance AI辅助编程环境搭建(理论上通过多个Api Key负载均衡达到无限免费Gemini 2.5 Pro)
前端·人工智能·vscode·后端·语言模型·负载均衡·ai编程
JIngJaneIL2 小时前
基于Java非遗传承文化管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot
+VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue心理健康管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
南部余额2 小时前
踩坑与解惑:深入理解 SpringBoot 自动配置原理与配置排除机制
java·spring boot·自动配置原理·import
狂炫冰美式3 小时前
不谈技术,搞点文化 🧀 —— 从复活一句明代残诗破局产品迭代
前端·人工智能·后端
木鹅.4 小时前
LangChain4j
java
永远都不秃头的程序员(互关)4 小时前
Java核心技术精要:高效实践指南
java·开发语言·性能优化