Tomcat 整体架构与启动流程:从 Server 到 Servlet 加载

刚接触 Java Web 时,我一直把 Tomcat 简单理解成"运行 Java 项目的服务器"。后来接触 Nginx、Apache HTTP Server,又看到 Tomcat 自己也能监听 8080 端口,几个概念很容易混在一起。

其实只要分清"谁负责接收请求"和"谁负责执行 Servlet",再顺着 Tomcat 的启动过程看一遍,它的整体结构并没有想象中复杂。

一、Tomcat、Apache 和 Nginx 有什么区别

这里所说的 Apache,一般是指 Apache HTTP Server,而不是整个 Apache 软件基金会。

Nginx 和 Apache HTTP Server 主要定位为 Web 服务器,擅长处理静态资源、反向代理、负载均衡和 HTTPS。Tomcat 则首先是一个 Servlet 容器,主要用于部署和运行 Java Web 应用。

简单对比如下:

对比项 Tomcat Nginx Apache HTTP Server
核心定位 Servlet 容器 Web 服务器、反向代理 Web 服务器
Java Servlet/JSP 原生支持 不直接支持 不直接支持
静态资源 可以处理,但不是主要优势 性能和并发能力较强 支持完善
反向代理 可以实现,但不常作为主要网关 非常常见 支持
常见场景 运行 Spring MVC、Servlet 应用 网关、负载均衡、静态资源 静态站点、模块化 Web 服务

Tomcat 本身也包含 HTTP Connector,所以它可以独立接收 HTTP 请求,并不是必须与 Nginx 搭配。开发环境中,我们直接访问 Spring Boot 的 8080 端口,本质上就是在访问内嵌 Tomcat。

生产环境经常采用下面的结构:

复制代码
浏览器 → Nginx → 多个 Tomcat 实例 → Java 应用

这样做并不是因为 Tomcat 无法提供 HTTP 服务,而是希望让 Nginx 负责域名、HTTPS、静态资源、限流和负载均衡,Tomcat 专心运行 Java 业务。

二、Tomcat 的启动过程

我们在 Linux 中通常执行:

复制代码
bin/startup.sh

Windows 中对应的是 startup.bat。脚本的主要作用是准备环境变量和 JVM 参数,随后调用 catalina.sh start,最终启动 Java 入口类:

复制代码
org.apache.catalina.startup.Bootstrap.main(args)

Tomcat 的启动过程可以概括为下面几步。

1. 脚本准备运行环境

2. Bootstrap 创建类加载器

3. Catalina 解析 server.xml

下面是一段简化配置:

复制代码
<Server port="8005" shutdown="SHUTDOWN">
    <Service name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1" />
        <Engine name="Catalina" defaultHost="localhost">
            <Host name="localhost" appBase="webapps" />
        </Engine>
    </Service>
</Server>

4. 初始化和启动各级组件

复制代码
启动脚本 → Bootstrap → Catalina → 解析 server.xml
        → 创建组件 → 初始化组件 → 启动组件 → 监听请求

三、Tomcat 的整体分层架构

Tomcat 的核心架构中,最常见的四个名称是 Server、Service、Connector 和 Container。

Server:代表整个 Tomcat

Server 是 server.xml 的最外层元素,代表整个 Catalina Servlet 容器。一个 Tomcat 实例通常只有一个 Server,其中可以包含多个 Service。

Service:连接网络层和容器层

Service 不是直接处理业务的组件,它更像一个组合层:一个 Service 可以包含多个 Connector,但通常只关联一个 Engine。

例如 HTTP 端口 8080 和 HTTPS 端口 8443 可以使用两个 Connector,最后把请求交给同一个 Engine,这样两种入口可以共享同一批 Web 应用。

Connector:负责网络和协议

Connector 负责监听端口、接收连接、解析 HTTP 或 AJP 协议,并把网络请求转换成 Tomcat 内部能够处理的 Request。业务处理完成后,它还负责把 Response 写回客户端。

Connector 解决的是"请求怎么进来、响应怎么出去",并不负责判断最终调用哪个 Servlet。

Container:负责找到并执行 Servlet

Container 负责请求在 Servlet 容器内部的处理。它还可以继续分为四层:

复制代码
Engine
└── Host
    └── Context
        └── Wrapper
  • Engine:处理当前 Service 中所有 Connector 转交的请求;

  • Host:代表一个虚拟主机,例如 www.example.com;

  • Context:代表一个 Web 应用,例如 /shop;

  • Wrapper:代表一个具体 Servlet,例如 Spring MVC 的 DispatcherServlet。

假设访问 http://localhost:8080/shop/order/list,Connector 先接收并解析请求,Engine 再找到 localhost 对应的 Host,Host 根据 /shop 找到 Context,最后由 Wrapper 调用对应的 Servlet。

可以把整体关系简单记为:Server 管整个 Tomcat,Service 组合入口与容器,Connector 处理网络,Container 执行业务请求。

四、load-on-startup 有什么作用

在传统 Java Web 项目的 web.xml 中,可以通过 <load-on-startup> 控制 Servlet 的创建时机:

复制代码
<servlet>
    <servlet-name>initServlet</servlet-name>
    <servlet-class>com.example.InitServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

如果配置的是非负整数,Tomcat 会在 Web 应用启动阶段创建 Servlet,并调用它的 init() 方法,而不是等第一次请求到来时才初始化。

多个 Servlet 都配置了 load-on-startup 时,数值较小的会优先加载。例如,值为 1 的 Servlet 通常早于值为 5 的 Servlet;相同数值之间的先后顺序不应依赖。如果配置负数或者没有配置,一般会在第一次请求匹配到该 Servlet 时再创建。

使用注解也能达到同样效果:

复制代码
@WebServlet(urlPatterns = "/init", loadOnStartup = 1)
public class InitServlet extends HttpServlet {
    @Override
    public void init() {
        System.out.println("应用启动时完成初始化");
    }
}

它常用于提前初始化必要资源,让第一次请求不用承担初始化耗时。不过,不建议把大量数据加载、长时间远程调用或者不稳定任务全部放进 init()。一旦初始化抛出异常,Servlet 可能不可用,甚至影响应用正常启动。

在 Spring Boot 项目中,我们很少直接配置 Servlet 的 load-on-startup,但它并没有消失。Spring MVC 的 DispatcherServlet 同样由 Servlet 容器管理,只是大部分注册工作由 Spring Boot 自动配置完成。

参考资料

相关推荐
mldong2 小时前
同一个节点接力办几轮,流程才往下走:jeeflow 的后加签
后端·架构
Decay__10 小时前
18_MySQL 智能巡检方案 —— 巡检项清单 / 一键巡检脚本 / 健康评分
运维·数据库·sql·mysql·架构
天远API15 小时前
零信任架构实战:基于天远运营商三要素详版V即时版构建自动化消费电子大促电商平台高价值权益秒杀与优惠券防羊毛高并发实名核验网关
运维·人工智能·架构·自动化
这个DBA有点耶16 小时前
信创场景下数据同步软件怎么选?对比开源CDC与原生闭环工具的结构性差异
数据库·mysql·架构
衡石科技18 小时前
衡石高性能分析架构:HQL、查询下推与多层加速的协同设计
架构·数据分析
Tokenfree19 小时前
换模型也要灰度:10% → 50% → 100%,每一档只看三个指标
架构
vivo互联网技术19 小时前
把 Agent 的判断与行动变成可恢复的软件事实|KDC 系列 工程篇
架构·agent·ai编程
用户0942485680320 小时前
第19章:库存扣减与秒杀系统:Redis 扛峰值流量
redis·架构·源码
leo在掘金20 小时前
2.8万亿MoE跑昇腾:0 Day适配改了啥
后端·架构
广凌科技1 天前
广凌校园物联网中台整体解决方案:三层架构驱动校园数字化智治
物联网·架构