Undertow使用说明

文章目录

Tomcat和Undertow比对

维度 Tomcat Undertow 备注
核心定位 传统 Servlet 容器,事实标准 轻量级、高性能 Web 服务器 + Servlet 容器 都可做 Spring Boot 内嵌容器
模型 基于 Connector + ProtocolHandler 的线程模型 事件驱动 + 非阻塞 IO(XNIO) Undertow 在高并发连接下更占优势
Servlet 支持 完整 Servlet/JSP 支持,生态成熟 支持 Servlet 规范,但自身更偏 Handler 管线 Spring 体系下一般不再推荐使用 JSP
协议 HTTP/1.1,支持 HTTP/2(8.5+ 配置或代理层) HTTP/1.1,支持 HTTP/2(取决于具体版本与配置) 实际多通过 Nginx 等代理终止 HTTP/2
WebSocket org.apache.tomcat.websocket 实现 内置 WebSocket 支持,事件驱动 两者都能满足常规 WebSocket 场景
AJP 原生支持 AJP 不强调 AJP 现代架构中 AJP 使用逐渐减少
性能(吞吐) 已足够强,大多数业务场景差异不明显 理论上延迟更低、吞吐略高 压测场景下 Undertow 通常略优
连接/线程模型 典型:一个请求绑定一个工作线程 非阻塞 IO,线程数可相对更少 极端高并发长连接下 Undertow 更有优势
内存占用 相对略高 相对略低 实际差异视场景与调优而定
配置复杂度 Spring Boot 下极简(server.tomcat.*) Boot 2.x 有 server.undertow.*;Boot 3.x 需自实现配置绑定 Boot 3 以后 Undertow 维护成本更高
生态与资料 非常丰富,Spring 官方默认 文档和案例相对较少 团队学习与排障成本 Tomcat 明显更低
Spring Boot 集成 默认内嵌容器,开箱即用 Boot 2.x 有官方 starter;Boot 3.x 官方 starter 已移除,需自集成或用三方 starter 升级/统一标准时推荐 Tomcat
适用场景 绝大部分企业级 Web/REST 系统 对极致性能、高并发连接、轻量部署有强需求且团队可接受维护成本的少数服务 适合作为"特种兵"容器而非常规默认

简单说明:

Undertow优点:

  • Undertow对大并发长连接(大量 keep-alive、WebSocket)更友好。在"简单业务逻辑 + 高并发压测"场景下,QPS 和 P99 延迟通常略优于 Tomcat。
  • io-threads + worker-threads 模型,更接近 Netty 的风格;利用 CPU 更均衡,不那么依赖"一个请求绑一个线程"的模式。
  • 不仅能用 Servlet,也可以用 Undertow 自己的 HttpHandler 管线;可以做一些容器的定制化开发。

Undertow缺点:

  • Spring Boot 3 开始,官方移除了 Undertow starter,意味着额外的维护和测试成本
  • 绝大部分中间件、监控探针、APM、诊断文档,都优先支持 Tomcat 场景。Undertow 虽然支持 Servlet,但在这些生态上的优先级明显低。
  • "最大连接数 / 队列"等参数不那么直观。Tomcat 有 max-connections / accept-count,很好理解。Undertow 没有 1:1 的"最大连接数"配置,需要你解释:连接处理能力由 io-threads + worker-threads + OS backlog + 网关综合决定

配置差异

tocmat

java 复制代码
server:
  #tomcat内核参数调优
  tomcat:
    #等待队列长度,默认100
    accept-count: 1000
    #最大链接数
    max-connections: 10000
    uri-encoding: UTF-8
    threads:
      #最大工作线程数,默认200
      max: 800
      #最小工作线程数,默认10
      min-spare: 100

Undertow

java 复制代码
server:
  # Undertow 内核参数调优
  undertow:
	# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
	# 不要设置过大,如果过大,启动项目会报错:打开文件数过多
    io-threads: 16
    # 工作线程数:对应 Tomcat 的 threads.max(负责真正业务处理),默认值是IO线程数*8
    worker-threads: 800
    # 使用直接内存缓冲区,提高 IO 性能
    direct-buffers: true
	# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
	# 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可
    buffer-size: 16384
	# 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region
	buffers-per-region: 1024
    # HTTP POST 最大体积(防止恶意大包)
    max-http-post-size: 20MB
	#用于解码 URL 的字符集,默认UTF-8
	url-charset: UTF-8
	#默认不需要配置
	threads:
		#为工作线程创建的 I O 线程数。默认值源自可用处理器的数量=16
		:io:
		工作线程数。默认是I O线程数的8倍:16*8=128
		worker:

最大同时连接数不是直接配置,通过 buffer-size和 buffers-per-region综合计算,也不能配置最小连接数

HttpHandler 案例

java 复制代码
public class UndertowHttpHandlerDemo {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    public static void main(String[] args) {
        Undertow server = Undertow.builder()
                .addHttpListener(8080, "0.0.0.0")
                // 使用 path() 做简单路由分发
                .setHandler(
                        path()
                                .addExactPath("/hello", new HelloHandler())
                                .addExactPath("/echo", new EchoHandler())
                                // POST /json,使用 BlockingHandler 方便读请求体
                                .addExactPath("/json", new BlockingHandler(new JsonHandler()))
                )
                .build();

        server.start();
        System.out.println("Undertow started on http://localhost:8080");
    }

    /**
     * 示例 1:最简单的 HttpHandler,返回纯文本
     */
    public static class HelloHandler implements HttpHandler {
        @Override
        public void handleRequest(HttpServerExchange exchange) throws Exception {
            // 设置响应头
            exchange.getResponseHeaders()
                    .put(Headers.CONTENT_TYPE, "text/plain; charset=UTF-8");
            // 写响应
            exchange.getResponseSender().send("Hello from Undertow HttpHandler!");
        }
    }


}
相关推荐
斯普信云原生组29 分钟前
Docker 开源软件应急处理方案及操作手册——Docker 服务启动故障处理
运维·docker·容器
斯普信云原生组34 分钟前
Docker 开源软件应急处理方案及操作手册——存储卷与数据持久化问题
docker·容器·eureka
斯普信云原生组34 分钟前
Docker 开源软件应急处理方案及操作手册——Docker Compose 应急处理
docker·容器·eureka
Traving Yu1 小时前
Kubernetes(K8s)
云原生·容器·kubernetes
hanzhuhuaa1 小时前
golang工程部署到docker容器(三)
运维·docker·容器
s9123601011 小时前
【docker】Ubuntu22使用skopeo离线推送镜像
运维·docker·容器
迷路爸爸1801 小时前
Docker 配置镜像源后仍然 `pull` 失败:问题、原因与解决方案
docker·容器·eureka
喝醉的小喵2 小时前
iptables 规则重启机器后丢失导致k8s网络不可用
网络·后端·容器·kubernetes·虚拟化
斯普信云原生组2 小时前
Docker 开源软件应急处理方案及操作手册——日常维护与监控命令集
docker·容器·eureka
迷路爸爸1802 小时前
Docker 入门学习笔记 01:它到底解决了什么问题,镜像和容器又是什么
服务器·笔记·学习·docker·容器