← 返回题目列表

Tomcat 的核心架构是什么?一个 HTTP 请求如何到达 Servlet?

高频 困难 第 12 / 23 题 更新于 2026/07/25
TomcatConnectorContainerServlet

简化版

Tomcat 由两大部分组成:Connector(连接器) 负责网络通信——监听端口、接收 TCP 连接、解析 HTTP 协议、封装成 Request/Response 对象;Container(容器,即 Catalina) 负责应用处理——按 Engine → Host → Context → Wrapper 四级容器层层定位到目标 Servlet 并调用它。请求从端口进入 Connector,解析后经 Adapter 交给 Container,Mapper 根据域名、路径、Servlet 映射找到对应的 Wrapper,执行 Filter 链后调用 Servlet 的 service() 方法。

详细版

整体架构(一个 Server 包含多个 Service):

Server(整个 Tomcat 实例)
 └─ Service(连接器 + 容器的组合,可有多个)
     ├─ Connector(Coyote):网络 + 协议  ← 可多个(HTTP、AJP)
     └─ Engine(Catalina 容器顶层)
         └─ Host(虚拟主机,对应一个域名,如 www.a.com)
             └─ Context(一个 Web 应用,对应一个 war/目录)
                 └─ Wrapper(封装一个具体的 Servlet)

两大核心组件分工:

组件名字职责
ConnectorCoyote监听端口、接收连接、解析 HTTP、封装 Request/Response、支持 BIO/NIO/APR
ContainerCatalina管理 Web 应用与 Servlet 生命周期,按四级容器定位并调用 Servlet

一个请求的完整流程:

  1. Connector 监听端口,接收 TCP 连接。
  2. 按 I/O 模型(现代默认 NIO)读取字节流,解析 HTTP 请求行、请求头、body。
  3. 封装成 Tomcat 的 Request/Response,通过 Adapter(CoyoteAdapter) 交给 Container。
  4. Mapper 根据 Host 头找 Host、context path 找 Context、servlet mapping 找 Wrapper。
  5. 请求依次流经 Engine → Host → Context → Wrapper 各级的 Pipeline(管道)+ Valve(阀门)
  6. 到 Wrapper 后执行 Filter 链,最后调用目标 Servlet 的 service()(Spring 应用里就是 DispatcherServlet)。

完整版教学

一、为什么要分 Connector 和 Container

Tomcat 本质是一个 Servlet 容器 + HTTP 服务器。它要干两件性质完全不同的事:

  • 对外:处理网络——怎么接收 TCP 字节、怎么解析 HTTP 协议、怎么把响应写回网络。这是协议和 I/O 层面的事,和「是哪个 Web 应用」无关。
  • 对内:处理应用——这个请求属于哪个域名、哪个 Web 应用、该调用哪个 Servlet,Servlet 怎么初始化销毁。这是应用容器层面的事,和「用什么协议进来」无关。

Tomcat 把这两件事拆成 Connector(管网络与协议)Container(管应用与 Servlet),用 Adapter 把两者解耦连接起来。好处是协议可以换、容器不变——支持 HTTP、AJP 等多种 Connector,共用同一套 Container。理解这个「网络层 / 应用层分离」是理解 Tomcat 架构的入口。

部分面向的问题典型对象变化时影响
Connector网络连接、协议解析、I/O 模型Endpoint、Processor、Adapter换 HTTP/AJP 或 BIO/NIO,不应改变 Servlet 管理方式
Container应用定位、生命周期、调用链Engine、Host、Context、Wrapper部署应用、映射 Servlet,不应关心 TCP 字节怎么读

记忆钩子:Connector 负责把“线上的字节”翻译成请求对象,Container 负责把“请求对象”送到正确的 Web 应用和 Servlet。

二、Connector(Coyote):把字节变成请求对象

Connector 又叫 Coyote,它内部关键分工:

  • Endpoint:负责底层 Socket 通信——监听端口、接收连接、管理 I/O 线程。这里决定了 I/O 模型:
    • BIO(老,一连接一线程,已淘汰);
    • NIO(现代默认,基于多路复用,少量线程扛大量连接);
    • NIO.2 / APR(进一步优化)。
  • Processor:负责协议解析——把 Endpoint 收到的字节流解析成 HTTP 请求(请求行、请求头、body),并把响应按 HTTP 格式写回。
  • Adapter(CoyoteAdapter)适配器,把 Coyote 自己的 Request/Response 转成标准的 Servlet API 的 HttpServletRequest/HttpServletResponse,交给 Container。

一句话:Connector 把「网络字节」变成「Servlet 能用的 Request 对象」。

三、Container 的四级容器:Engine → Host → Context → Wrapper

Container(Catalina)是一个四级嵌套的结构,每一级对应一个概念:

  • Engine(引擎):容器顶层,代表整个 Catalina 引擎,一个 Service 只有一个 Engine。
  • Host(虚拟主机):对应一个域名(如 www.example.com)。一个 Tomcat 可以配多个 Host,实现虚拟主机(不同域名指向不同应用)。
  • Context(上下文):对应一个 Web 应用(一个 war 包或一个目录),有自己的 context path(如 /app)、独立的类加载器、独立的 Servlet 集合。
  • Wrapper(包装器):最底层,封装一个具体的 Servlet——管理这个 Servlet 的加载、初始化、service() 调用、销毁。

这四级是父子包含关系:一个 Engine 有多个 Host,一个 Host 有多个 Context,一个 Context 有多个 Wrapper。请求定位 Servlet 的过程,就是沿这条层级从上往下找的过程。

四、Mapper:请求如何精确定位到 Servlet

请求进入 Container 后,靠 Mapper(映射器) 一步步定位到目标 Wrapper:

  1. 定位 Host:看 HTTP 请求头里的 Host(域名),匹配到对应的 Host 容器。
  2. 定位 Context:看请求 URL 的 context path(如 /app/user/list 里的 /app),匹配到对应的 Web 应用(Context)。
  3. 定位 Wrapper:在 Context 内,看 servlet mappingweb.xml 或注解里配的 URL 映射,如 /user/*),匹配到对应的 Servlet(Wrapper)。

举例 http://www.a.com/app/user/list:Host = www.a.com,Context = /app,剩下 /user/list 按 servlet mapping 找到处理它的 Servlet。这就是「域名 → 应用 → Servlet」的三层映射。

GET /app/user/list HTTP/1.1
Host: www.a.com

Connector 解析 HTTP
  -> Mapper 找 Host: www.a.com
  -> Mapper 找 Context: /app
  -> Mapper 找 Wrapper: /user/*
  -> Filter 链
  -> Servlet.service()

如果同一台 Tomcat 同时部署 2 个 Host、每个 Host 下 3 个 Context,每个 Context 有 20 个 Servlet,Mapper 的价值就在于把一次请求从这些候选项里快速缩小到 1 个 Wrapper,而不是让业务层自己猜。

五、Pipeline 与 Valve:容器的责任链扩展点

Container 的每一级(Engine/Host/Context/Wrapper)都有一个 Pipeline(管道),管道上串着若干 Valve(阀门)。请求流经某一级容器时,会依次经过该级 Pipeline 上的所有 Valve,最后由管道末端的 BasicValve 把请求传给下一级容器。

这本质是一个责任链模式——Valve 是 Tomcat 内部的横切扩展点,可以在请求流经各级容器时插入逻辑,例如:

  • AccessLogValve:记录访问日志(在 Host 级)。
  • ErrorReportValve:错误页面处理。
  • 认证、限流 等自定义 Valve。

Valve 和 Filter 的区别:Valve 是 Tomcat 容器级别的(对所有应用生效、是 Tomcat 私有机制),Filter 是 Servlet 规范级别的(在具体 Web 应用内、跨容器可移植)。请求是先过 Valve(容器级),到 Wrapper 后再过 Filter(应用级),最后才到 Servlet。

六、和 Spring MVC 的关系(易混点)

一个高频易混点:Spring MVC 的 DispatcherServlet 对 Tomcat 而言,就是一个普通的 Servlet。

  • Tomcat 负责把请求送到 DispatcherServlet(它是 Context 里的一个 Wrapper)——这是 Tomcat 的 servlet mapping 层面的映射(通常 DispatcherServlet 映射 /)。
  • 进了 DispatcherServlet 之后,Spring MVC 内部再用 HandlerMapping 找到具体的 @Controller 方法——这是 Spring 层面的映射。

两层映射不要混:Tomcat 只管「请求 → 哪个 Servlet」,Spring MVC 管「进了 DispatcherServlet 后 → 哪个 Controller」。理解这一点,排查「请求到不了 Controller」时才能分清是 Tomcat 层没进来、还是 Spring 层没匹配到。

七、排查「请求到不了目标」的分层思路

当请求没到达预期的 Controller/Servlet 时,按架构分层从外往里排查效率最高:

  1. 端口 / Connector:请求有没有进到 Tomcat?看端口是否正确、Connector 是否正常、防火墙。
  2. Host / Context:域名和应用路径对不对?context path 配错会 404。
  3. Servlet mapping / Filter:URL 映射对不对?有没有 Filter 提前拦截返回了?
  4. Spring 层:进了 DispatcherServlet 后,HandlerMapping 有没有匹配到 Controller?

分层排查比一上来就怀疑业务代码快得多——这正是理解 Tomcat 架构的实战价值。

八、常见误区与追问

  • 误区:Tomcat 只是简单调用 Servlet。 调用 Servlet 之前还有 Connector 解析、Adapter 适配、Mapper 定位、Pipeline/Valve、Filter 链等多层处理。
  • 误区:Host、Context、Wrapper 都是同一个概念。 Host 对应域名,Context 对应 Web 应用,Wrapper 才封装具体 Servlet,层级不同。
  • 追问:Connector 和 Container 为什么要解耦? 这样网络协议和应用容器可以独立演进,一个 Container 可以被不同 Connector 使用。
  • 追问:Valve 和 Filter 最大区别是什么? Valve 是 Tomcat 私有的容器级扩展点,Filter 是 Servlet 规范的应用级扩展点,Filter 更可移植。
  • 误区:Spring MVC 的 Controller 是 Tomcat 直接找到的。 Tomcat 只找到 DispatcherServlet,Controller 方法由 Spring MVC 的 HandlerMapping 再匹配。
  • 追问:请求 404 应该按什么顺序排查? 先看端口和 Connector,再看 Host/Context,再看 servlet mapping/Filter,最后看 Spring HandlerMapping。

九、加强记忆

Tomcat = Connector(Coyote,管网络+协议)+ Container(Catalina,管应用+Servlet),用 Adapter 解耦。Connector 三件套:Endpoint(Socket,决定 BIO/NIO/APR)、Processor(解析 HTTP)、Adapter(转成 Servlet API)。Container 四级:Engine(引擎)→ Host(域名)→ Context(Web 应用)→ Wrapper(Servlet),靠 Mapper 按「域名→应用→servlet mapping」三层定位。每级容器有 Pipeline + Valve(容器级责任链扩展点,区别于应用级的 Filter)。请求路径:端口 → Connector 解析 → Adapter → Mapper 定位 Wrapper → Valve → Filter → Servlet.service()。Spring MVC 的 DispatcherServlet 只是一个 Servlet,Tomcat 映射和 Spring HandlerMapping 是两层别混。