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线程 → 内核发送 → 网络传输 → 浏览器
相关推荐
回家路上绕了弯5 分钟前
为什么 AI 写代码时,总喜欢“防御性编程”?
后端
灯澜忆梦8 分钟前
【Redis中间件】#4 | 进阶数据类型语法
redis·后端
广州山泉婚姻11 分钟前
前后端分离的核心优势
前端·后端
IT_陈寒30 分钟前
Vue的响应式让我加班到凌晨,问题竟出在这个不起眼的地方
前端·人工智能·后端
乱码三千42 分钟前
使用 Docker-compose 搭建SRS直播中转服务端
后端·架构·github
y1su42 分钟前
【Leetcode】1477. 找两个和为目标值且不重叠的子数组
数据结构·后端·算法·leetcode·职场和发展
愛芳芳1 小时前
Swagger2 多环境动态配置实战指南
java·后端·maven·springboot·swagger
JaguarJack2 小时前
PHP 8.6 只是个小版本,三十项弃用却已在为 PHP 9.0 铺路
后端·php·服务端
BingoGo2 小时前
PHP 8.6 只是个小版本,三十项弃用却已在为 PHP 9.0 铺路
后端·php
Bs_MoneyMagnet5 小时前
基于springboot+vue的滑雪场票务与装备租赁系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计