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

完整的时序图

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

sequenceDiagram participant U as 用户/浏览器 participant DNS as DNS服务器 participant OS as 操作系统
内核/网卡 participant UT as Undertow
I/O线程 participant WT as Undertow
工作线程 participant SCI as ServletContext-
Initializer participant DS as Dispatcher-
Servlet participant SC as Spring容器
(ApplicationContext) participant MVC as Spring MVC
组件 participant DB as 数据库 Note over U, DB: 阶段1: 应用启动阶段 rect rgb(240, 255, 240) Note over SC, SCI: 1. Spring容器启动 SC->>SC: SpringApplication.run()
创建ApplicationContext SC->>SC: 扫描@Component、@Bean等
初始化所有单例Bean SC->>DS: 创建DispatcherServlet Bean
@Bean DispatcherServlet Note over SC, SCI: 2. 自动配置机制 SC->>SCI: 创建ServletRegistrationBean
(实现ServletContextInitializer) SCI->>SCI: 包含DispatcherServlet和URL映射配置 Note over UT, SCI: 3. Undertow服务器启动 SC->>UT: 创建Undertow实例
配置I/O线程(16)和工作线程(512) UT->>UT: 绑定端口8080
启动事件监听循环 Note over UT, SCI: 4. Servlet注册回调 UT->>SCI: 回调onStartup()方法
(通过TomcatStarter桥接) SCI->>UT: 调用servletContext.addServlet()
注册DispatcherServlet到Undertow UT->>UT: 完成Servlet注册
更新URL映射表 end Note over U, DB: 阶段2: DNS解析和网络传输 rect rgb(240, 248, 255) U->>DNS: DNS查询
example.com → 192.168.1.100 DNS->>U: 返回IP地址 U->>OS: HTTP请求 GET /api/users
TCP三次握手建立连接 OS->>OS: 网卡接收数据→DMA→内核缓冲区 end Note over U, DB: 阶段3: Undertow接收和处理 rect rgb(255, 248, 240) OS->>UT: 通过epoll通知数据就绪
I/O线程从内核缓冲区读取 UT->>UT: 解析HTTP协议
创建HttpServerExchange UT->>WT: 从线程池(512)借用工作线程
传递请求信息 Note over WT, DS: 4. Servlet处理链 WT->>DS: 调用service()方法
请求进入Spring MVC世界 DS->>MVC: doDispatch()开始处理
查找HandlerMapping MVC->>MVC: 执行Interceptor.preHandle()
参数绑定验证 MVC->>SC: 调用@Controller方法
执行业务逻辑 SC->>DB: 执行SQL查询
工作线程等待数据库响应 DB->>SC: 返回查询结果 SC->>MVC: 返回ModelAndView
执行Interceptor.postHandle() MVC->>DS: 处理完成
准备响应数据 DS->>WT: 返回响应给工作线程 WT->>UT: 工作线程释放
响应数据交还I/O线程 end Note over U, DB: 阶段4: 响应返回 rect rgb(248, 240, 255) UT->>OS: I/O线程写入内核发送缓冲区 OS->>U: 操作系统组包发送HTTP响应 U->>U: 浏览器接收响应
解析HTML/JSON渲染页面 UT->>UT: 保持HTTP连接
等待下一个请求 end Note over U, DB: 阶段5: 连接管理(后续请求) U->>UT: 同一连接的后续请求
复用现有TCP连接 UT->>WT: 直接分配工作线程处理
跳过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 正在重塑职场:有人乘风破浪,有人悄然掉队
后端
用户97436970725282 小时前
5分钟搭建企业级实时消息推送系统
后端·websocket
counting money2 小时前
Spring框架基础(配置篇)
java·后端·spring
生活真难2 小时前
SpringCloud - 任务调度 - xxl-job
后端·spring·spring cloud
Nyarlathotep01133 小时前
JUC工具(3):StampedLock的基础和原理
java·后端
直奔標竿3 小时前
Java开发者AI转型第二十二课!Spring AI 个人知识库实战(一)——架构搭建与核心契约落地
java·人工智能·后端·spring·架构
清汤饺子3 小时前
【译】我的 AI 进阶之路:从怀疑到深度整合
前端·javascript·后端
无厚4 小时前
Spring Boot中LLM流式交互的核心原理
后端·设计