Spring Boot + Undertow 全栈架构深度剖析时序图

完整的时序图

涵盖从Spring容器启动、Undertow集成、Servlet注册,到用户请求的完整生命周期

sequenceDiagram participant U as 用户/浏览器 participant DNS as DNS服务器 participant OS as 操作系统<br>内核/网卡 participant UT as Undertow<br>I/O线程 participant WT as Undertow<br>工作线程 participant SCI as ServletContext-<br>Initializer participant DS as Dispatcher-<br>Servlet participant SC as Spring容器<br>(ApplicationContext) participant MVC as Spring MVC<br>组件 participant DB as 数据库 Note over U, DB: 阶段1: 应用启动阶段 rect rgb(240, 255, 240) Note over SC, SCI: 1. Spring容器启动 SC->>SC: SpringApplication.run()<br>创建ApplicationContext SC->>SC: 扫描@Component、@Bean等<br>初始化所有单例Bean SC->>DS: 创建DispatcherServlet Bean<br>@Bean DispatcherServlet Note over SC, SCI: 2. 自动配置机制 SC->>SCI: 创建ServletRegistrationBean<br>(实现ServletContextInitializer) SCI->>SCI: 包含DispatcherServlet和URL映射配置 Note over UT, SCI: 3. Undertow服务器启动 SC->>UT: 创建Undertow实例<br>配置I/O线程(16)和工作线程(512) UT->>UT: 绑定端口8080<br>启动事件监听循环 Note over UT, SCI: 4. Servlet注册回调 UT->>SCI: 回调onStartup()方法<br>(通过TomcatStarter桥接) SCI->>UT: 调用servletContext.addServlet()<br>注册DispatcherServlet到Undertow UT->>UT: 完成Servlet注册<br>更新URL映射表 end Note over U, DB: 阶段2: DNS解析和网络传输 rect rgb(240, 248, 255) U->>DNS: DNS查询<br>example.com → 192.168.1.100 DNS->>U: 返回IP地址 U->>OS: HTTP请求 GET /api/users<br>TCP三次握手建立连接 OS->>OS: 网卡接收数据→DMA→内核缓冲区 end Note over U, DB: 阶段3: Undertow接收和处理 rect rgb(255, 248, 240) OS->>UT: 通过epoll通知数据就绪<br>I/O线程从内核缓冲区读取 UT->>UT: 解析HTTP协议<br>创建HttpServerExchange UT->>WT: 从线程池(512)借用工作线程<br>传递请求信息 Note over WT, DS: 4. Servlet处理链 WT->>DS: 调用service()方法<br>请求进入Spring MVC世界 DS->>MVC: doDispatch()开始处理<br>查找HandlerMapping MVC->>MVC: 执行Interceptor.preHandle()<br>参数绑定验证 MVC->>SC: 调用@Controller方法<br>执行业务逻辑 SC->>DB: 执行SQL查询<br>工作线程等待数据库响应 DB->>SC: 返回查询结果 SC->>MVC: 返回ModelAndView<br>执行Interceptor.postHandle() MVC->>DS: 处理完成<br>准备响应数据 DS->>WT: 返回响应给工作线程 WT->>UT: 工作线程释放<br>响应数据交还I/O线程 end Note over U, DB: 阶段4: 响应返回 rect rgb(248, 240, 255) UT->>OS: I/O线程写入内核发送缓冲区 OS->>U: 操作系统组包发送HTTP响应 U->>U: 浏览器接收响应<br>解析HTML/JSON渲染页面 UT->>UT: 保持HTTP连接<br>等待下一个请求 end Note over U, DB: 阶段5: 连接管理(后续请求) U->>UT: 同一连接的后续请求<br>复用现有TCP连接 UT->>WT: 直接分配工作线程处理<br>跳过DNS和连接建立阶段

关键环节的详细说明

1. Spring与Undertow的集成细节(阶段1)

自动配置机制

java 复制代码
// Spring Boot自动配置类
@Configuration
@ConditionalOnClass({Servlet.class, Undertow.class})
public class UndertowServletWebServerFactoryConfiguration {
    
    @Bean
    public UndertowServletWebServerFactory undertowServletWebServerFactory() {
        // 创建Undertow工厂
        return new UndertowServletWebServerFactory();
    }
}

// Servlet注册(关键桥梁)
@Bean
public ServletRegistrationBean<DispatcherServlet> dispatcherServletRegistration() {
    // 这个Bean实现了ServletContextInitializer接口
    return new ServletRegistrationBean<>(dispatcherServlet(), "/");
}

Undertow启动过程

java 复制代码
// Spring Boot启动Undertow的简化流程
public class UndertowWebServer implements WebServer {
    public void start() {
        // 1. 创建Undertow Builder
        Undertow.Builder builder = Undertow.builder()
            .addHttpListener(port, "0.0.0.0")
            .setIoThreads(16)    // I/O线程
            .setWorkerThreads(512) // 工作线程
            .setHandler(handlers);
        
        // 2. 启动服务器
        this.undertow = builder.build();
        this.undertow.start();
        
        // 3. 回调ServletContextInitializer
        for (ServletContextInitializer initializer : initializers) {
            initializer.onStartup(this.getServletContext());
        }
    }
}

2. 请求处理链的详细流程(阶段3)

Undertow → Spring MVC的转换

java 复制代码
// Undertow的HttpHandler处理请求
public class ServletInitialHandler implements HttpHandler {
    public void handleRequest(HttpServerExchange exchange) {
        // 1. 将Undertow的Exchange转换为Servlet的Request/Response
        ServletRequestContext servletRequestContext = 
            new ServletRequestContext(exchange, servletContext);
        
        HttpServletRequest request = servletRequestContext.getServletRequest();
        HttpServletResponse response = servletRequestContext.getServletResponse();
        
        // 2. 创建Filter链并执行
        ApplicationFilterChain filterChain = 
            ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
        
        // 3. 最终调用DispatcherServlet.service()
        filterChain.doFilter(request, response);
    }
}

Spring MVC内部处理

java 复制代码
// DispatcherServlet的核心处理流程
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
    // 1. 查找HandlerMapping
    HandlerExecutionChain mappedHandler = getHandler(request);
    
    // 2. 获取HandlerAdapter
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    // 3. 执行拦截器前置处理
    if (!mappedHandler.applyPreHandle(request, response)) return;
    
    // 4. 实际执行Controller方法
    ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler());
    
    // 5. 执行拦截器后置处理
    mappedHandler.applyPostHandle(request, response, mv);
    
    // 6. 处理结果渲染
    processDispatchResult(request, response, mappedHandler, mv, null);
}

3. 网络层面的细节(阶段2和4)

DNS解析过程

  1. 浏览器缓存检查 → 2. 系统缓存检查 → 3. 路由器缓存检查 → 4. ISP DNS缓存 → 5. 递归查询 → 6. 返回IP地址

TCP连接复用

  1. 建立连接后,后续请求复用同一连接
  2. 第一次请求: TCP握手 → HTTP请求/响应
  3. 第二次请求: HTTP请求/响应(复用连接)
  4. 第三次请求: HTTP请求/响应(复用连接)

4. 线程模型的关键点

Undertow的两级线程池

  • I/O线程(16个) :非阻塞处理网络I/O,不执行业务逻辑
  • 工作线程(512个) :阻塞式处理业务逻辑,可被挂起等待IO

优势: 工作线程在等待数据库时可以处理其他请求

  • 工作线程1: 开始处理请求A → 等待数据库 → 挂起
  • 工作线程1: 被唤醒处理请求B → 快速计算 → 返回响应
  • 工作线程1: 数据库响应到达 → 继续处理请求A → 返回响应

完整数据流总结

  1. 启动阶段:Spring容器 → 创建Bean → 启动Undertow → 注册Servlet
  2. 请求接收:DNS解析 → 建立TCP连接 → 内核接收 → Undertow I/O线程
  3. 业务处理:工作线程 → DispatcherServlet → Spring MVC → 业务逻辑 → 数据库
  4. 响应返回:处理结果 → 工作线程 → I/O线程 → 内核发送 → 网络传输 → 浏览器
相关推荐
山水洛行1 小时前
AI Agent 智能体记忆:从检索到被治理的数据系统
后端
卷无止境2 小时前
C++20 的概念与约束:让模板编程终于"说人话"
后端
Ai拆代码的曹操2 小时前
一次排查三种连接泄漏模式,再也不怕 HikariCP 连接池爆满了
后端
咪库咪库咪2 小时前
Cypher入门
后端
雪隐3 小时前
个人电脑玩AI-08让5060 Ti给你打工——我拿 Unlimited-OCR扫了 600 页书,然后悟了
人工智能·后端
AskHarries3 小时前
用 OpenClaw 做一份完整 PPT:从主题、提纲到 slide deck
后端·程序员
Csvn3 小时前
Linux 常用操作命令合集与运维实战
后端
卷无止境3 小时前
现代C++ 编译器生态及其对编程规范的影响
后端
云技纵横3 小时前
一个 @Async,把 @Transactional 的事务边界打穿了
后端·面试