一、Tomcat 基础认知
1. 核心概念
Tomcat 是 Apache 软件基金会旗下开源、轻量级的 Java Web 服务器与 Servlet 容器 ,核心价值是实现 Java EE 规范中的 Servlet 规范 和 JSP 规范,是中小型 Java Web 应用部署的标准载体,也可作为大型架构中动态资源的处理节点(与 Nginx 配合实现动静分离)。
1.1 核心定位与核心属性
| 属性 | 核心说明 |
|---|---|
| 角色定位 | 既是Web 服务器 (处理静态资源请求),也是Servlet 容器(运行 Java 动态代码),是 Java Web 应用的运行基座 |
| 规范实现 | 实现 Servlet 3.x/4.x/5.x 与 JSP 2.x/3.x 规范,兼容主流 Java 开发框架(Spring MVC、Struts 等) |
| 轻量化特性 | 体积小、部署简单、资源占用低,支持热部署,适合开发测试与中小规模生产环境 |
| 架构适配 | 常与 Nginx 配合使用:Nginx 处理静态资源、反向代理,Tomcat 专注处理动态 Java 请求 |
1.2 Tomcat 核心容器架构
Tomcat 的核心架构以分层容器为核心,容器间呈父子包含关系,决定了请求的处理路径与部署逻辑,是理解 Tomcat 运行机制的关键:
| 容器层级 | 名称 | 核心作用 | 配置载体 | 核心特点 |
|---|---|---|---|---|
| 顶层容器 | Server | 代表整个 Tomcat 实例,包含一个或多个 Service | server.xml 中 <Server> 标签 |
负责 Tomcat 启动 / 关闭,监听关闭信号(如 SHUTDOWN 端口) |
| 服务容器 | Service | 关联一个 Engine 和多个 Connector,实现 "连接处理" 与 "请求处理" 的解耦 | server.xml 中 <Service> 标签 |
一个 Service 对应一套独立的 "连接 - 处理" 体系,支持多端口监听 |
| 引擎容器 | Engine | 处理 Service 下所有 Connector 接收的请求,是请求处理的核心引擎 | server.xml 中 <Engine> 标签 |
包含多个 Host,负责将请求路由到对应虚拟主机(Host) |
| 主机容器 | Host | 代表一个虚拟主机(域名),包含多个 Web 应用(Context) | server.xml 中 <Host> 标签 |
配置域名映射,管理该域名下的所有 Web 应用部署 |
| 应用容器 | Context | 代表一个独立的 Java Web 应用,是最小的部署单元 | server.xml 或 context.xml |
对应 webapps 下的一个应用目录,处理该应用的所有请求 |
1.3 核心功能组件
容器架构的运行依赖核心功能组件的协作,核心组件及作用如下:
| 组件 | 核心职责 | 关键说明 |
|---|---|---|
| Connector(连接器) | 接收客户端请求,封装请求数据,转发至 Engine | 监听指定端口(如 8080),支持 HTTP/HTTPS/AJP 协议,是 Tomcat 与客户端的通信入口 |
| Servlet 容器 | 运行 Servlet 类,处理动态请求,生成响应 | 是 Tomcat 的核心能力,负责 Servlet 的实例化、初始化、执行与销毁,遵循 Servlet 生命周期 |
| JSP 引擎(Jasper) | 编译 JSP 页面为 Servlet 类 | 将 JSP 代码转换为 Java 源码并编译为 class 文件,后续按 Servlet 逻辑执行 |
| Executor(线程池) | 管理请求处理线程,优化性能 | 统一管理线程资源,避免频繁创建销毁线程,是 Tomcat 性能调优的核心节点 |
| Realm(域) | 身份认证与权限控制 | 实现用户认证(如用户名密码校验),支持内存、数据库、LDAP 等多种认证方式 |
1.4 Tomcat 关键目录结构(核心部署基础)
Tomcat 以解压包形式部署,核心目录的功能是配置、部署、日志与运行的基础,所有操作均围绕这些目录展开:
| 目录名称 | 核心功能 | 关键文件 / 内容 |
|---|---|---|
bin |
启动 / 关闭脚本目录 | startup.sh/startup.bat(启动)、shutdown.sh/shutdown.bat(关闭)、catalina.sh(核心运行脚本) |
conf |
核心配置目录 | server.xml(容器架构配置)、web.xml(全局 Web 应用配置)、context.xml(应用上下文配置)、tomcat-users.xml(用户认证配置) |
lib |
依赖库目录 | Tomcat 核心 Jar 包、第三方依赖 Jar 包(所有 Web 应用共享) |
webapps |
应用部署目录 | 存放 Web 应用(WAR 包或解压目录),Tomcat 启动时自动部署该目录下的应用 |
logs |
日志目录 | catalina.out(核心运行日志)、localhost_access_log.*.txt(访问日志)、localhost.log(本地主机日志) |
work |
工作目录 | 存放 JSP 编译后的 Servlet 源码与 class 文件,重启 Tomcat 可删除该目录清理编译缓存 |
temp |
临时文件目录 | Tomcat 运行时生成的临时文件,重启后自动清理 |
1.5 Tomcat 核心运行模式(性能核心维度)
Tomcat 的 Connector 支持三种 I/O 运行模式,直接决定并发处理能力与资源占用,是性能调优的首要选择:
| 运行模式 | 全称 | 核心特点 | 并发能力 | 适用场景 |
|---|---|---|---|---|
| BIO | Blocking I/O(阻塞 I/O) | 一个请求占用一个线程,线程阻塞等待响应,资源利用率低 | 低(适合低并发场景) | 开发测试环境,老旧系统兼容 |
| NIO | Non-Blocking I/O(非阻塞 I/O) | 基于多路复用技术,一个线程处理多个请求,非阻塞等待 | 中高(Tomcat 8+ 默认模式) | 生产环境主流选择,适配中高并发 |
| AIO | Asynchronous I/O(异步 I/O) | 基于异步事件驱动,请求处理完全异步,线程无等待 | 高(需操作系统支持) | 超高并发场景,Linux 环境下推荐 |
2. 核心应用场景
1. 独立部署 Java Web 应用
- 适用场景:中小型企业官网、内部 OA 系统、电商后台、教学演示等轻量级 Java Web 项目。
- 架构特点 :直接将 WAR 包或解压后的应用部署到
webapps目录,Tomcat 作为唯一的 Web 服务器,同时处理静态资源(HTML/CSS/JS)和动态请求(Servlet/JSP)。 - 核心优势:部署流程极简、资源占用低,无需额外依赖,适合快速上线和轻量业务场景。
2. 与 Nginx 配合实现动静分离
- 适用场景:中大型 Web 项目(如电商平台、内容门户、SaaS 服务),对静态资源访问速度和并发能力有较高要求。
- 架构特点 :
- Nginx 监听 80/443 端口,负责处理静态资源(图片、CSS、JS、静态 HTML),并提供 HTTPS 加密、缓存优化等能力;
- 动态请求(如 JSP、Servlet 接口)通过反向代理转发到后端 Tomcat 集群(8080 端口);
- 可配合负载均衡策略(轮询、加权轮询)分发请求到多台 Tomcat 节点。
- 核心优势:大幅减轻 Tomcat 的静态资源处理压力,提升整体并发能力与响应速度,同时实现服务解耦与高可用。
3. 微服务架构中的应用容器
- 适用场景:Spring Boot / Spring Cloud 微服务项目,以及云原生应用部署。
- 架构特点 :
- 微服务应用以可执行 JAR 包形式打包,内嵌 Tomcat(或其他 Servlet 容器),独立部署;
- 每个微服务对应一个独立的 Tomcat 实例,通过服务注册中心(如 Nacos、Eureka)实现服务发现与治理;
- 可容器化部署(Docker/K8s),实现弹性扩缩容。
- 核心优势:轻量化、独立部署、便于扩展,完美适配微服务的分布式架构理念。
4. 开发与测试环境的轻量级服务器
- 适用场景:开发调试、单元测试、集成测试、教学实验等场景。
- 架构特点 :
- 开发工具(如 IntelliJ IDEA、Eclipse)可直接内嵌 Tomcat,一键启动应用;
- 本地部署 Tomcat,快速部署测试代码,支持热部署(修改代码后无需重启服务)。
- 核心优势:启动速度快、配置灵活,大幅提升开发与测试效率,是 Java 开发者的 "标配工具"。
5. 高可用集群部署
- 适用场景:对可用性和并发能力要求极高的生产环境(如大型电商、金融交易系统、政务平台)。
- 架构特点 :
- 多台 Tomcat 节点组成集群,前端通过负载均衡器(Nginx、HAProxy、LVS)分发请求;
- 通过 Session 共享方案(如 Redis、Memcached)实现跨节点会话同步;
- 配合 Keepalived 等工具实现负载均衡器的高可用,避免单点故障。
- 核心优势:消除单点故障,提升系统并发承载能力,保障服务 7×24 小时稳定运行。
6. 传统企业级应用的 Servlet 容器
- 适用场景:遗留 Java EE 应用(如基于 Struts、EJB 的企业级系统),以及对 Servlet/JSP 规范兼容性要求高的项目。
- 架构特点:Tomcat 作为核心 Servlet 容器,部署传统企业级应用,兼容旧版 Java EE 规范,支持 JNDI、JDBC 资源池等企业级特性。
- 核心优势:稳定可靠、生态成熟,保护企业在传统应用上的技术投资,同时可逐步向微服务架构演进。
二、实验:Tomcat 单机安装与部署
1. 实验步骤
1.1 安装 JDK 环境(Tomcat 运行依赖)
Tomcat 是 Java 开发的程序,必须先安装 Java 运行环境,此处选择开源的 OpenJDK 1.8:
yum install java-1.8.0-openjdk.x86_64 -y
安装完成后可通过 java -version 验证,输出 1.8.0 版本信息即表示安装成功。
1.2 下载 Tomcat 安装包并解压
从 Apache 官方源下载 Tomcat 9.0.107 压缩包,解压到 /usr/local 目录并简化目录名:
# 下载安装包
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.115/bin/apache-tomcat-9.0.107.tar.gz
# 解压到 /usr/local 目录
tar zxf apache-tomcat-9.0.107.tar.gz -C /usr/local
# 进入 /usr/local 并重命名,简化后续操作
cd /usr/local/
mv apache-tomcat-9.0.107/ tomcat
1.3 临时启动 Tomcat 并验证启动状态
通过 bin 目录下的脚本启动 Tomcat,并检查默认 8080 端口的监听状态:
# 进入 Tomcat 启动脚本目录
cd tomcat/bin/
# 启动 Tomcat
./startup.sh
# 验证 8080 端口监听(Tomcat 默认服务端口)
netstat -antlupe | grep 8080
启动成功标识:执行 ./startup.sh 后输出 Tomcat started.;netstat 命令输出包含 :::8080 的 LISTEN 状态。
1.4 配置 Tomcat 系统服务
临时启动仅适用于测试,配置 systemd 系统服务可实现 Tomcat 开机自启、便捷的启停管理,步骤如下:
重载系统服务并设置 Tomcat 开机自启,验证服务状态:
# 创建 Tomcat 环境配置文件,指定 JAVA_HOME 路径
vim /usr/local/tomcat/conf/tomcat.conf
# 写入以下内容并保存
JAVA_HOME=/etc/alternatives/jre
# 创建 systemd 服务文件 /lib/systemd/system/tomcat.service
vim /lib/systemd/system/tomcat.service
# 写入以下完整配置
[Unit]
Description=Tomcat
After=syslog.target network.target
[Service]
Type=forking
EnvironmentFile=/usr/local/tomcat/conf/tomcat.conf
ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/usr/local/tomcat/bin/shutdown.sh
PrivateTmp=true
User=tomcat
Group=tomcat
[Install]
WantedBy=multi-user.target
# 创建 Tomcat 专用用户
# 创建无登录权限的 tomcat 用户和用户组
useradd -s /sbin/nologin -M tomcat
# 为 tomcat 用户授权 Tomcat 整个目录
chown tomcat.tomcat /usr/local/tomcat/ -R
# 重载系统服务并设置 Tomcat 开机自启,验证服务状态:
# 重载 systemd 配置,使新服务生效
systemctl daemon-reload
# 启动 Tomcat 并设置开机自启
systemctl enable --now tomcat
# 验证 Tomcat 相关端口监听
netstat -antlupe | grep java
服务配置成功标识 :netstat 命令输出 8080(服务端口)和 8005(管理端口)的 LISTEN 状态。
2. 实验结果
- 核心总结
| 核心知识点 | 核心风险 | 实操落地步骤 | 关键注意事项 | |
|---|---|---|---|---|
| Tomcat 运行强依赖 JDK,需配置正确 JAVA_HOME | 配置错误会导致 Tomcat 启动失败,抛出JAVA_HOME not set类异常 |
1. 安装对应版本 JDK(Tomcat 9 + 推荐 JDK 8/11);2. 配置环境变量:echo "export JAVA_HOME=/usr/local/jdk1.8.0_381" >> /etc/profile``echo "export PATH=\$JAVA_HOME/bin:\$PATH" >> /etc/profile3. 生效配置:source /etc/profile4. 验证:java -version、echo $JAVA_HOME |
1. JDK 版本需与 Tomcat 兼容(如 Tomcat 10 不兼容 JDK 7);2. 避免配置为JRE_HOME,Tomcat 运行需完整 JDK |
|
| 临时启停脚本(startup.sh/shutdown.sh)存在服务中断风险 | 关闭终端、服务器重启后,Tomcat 进程会终止,服务不可用 | 方案:将 Tomcat 注册为系统服务,实现开机自启与后台运行:1. 创建服务文件:vi /usr/lib/systemd/system/tomcat.service2. 写入配置(见下文);3. 重载服务:systemctl daemon-reload4. 启动并开机自启:systemctl start tomcat && systemctl enable tomcat |
注册系统服务后,禁止再使用临时脚本启停,避免进程冲突 | |
| 禁止 root 用户运行 Tomcat,需创建专用用户 | root 运行会大幅提升服务器安全风险(如被攻击后获取系统最高权限) | 1. 创建用户组与用户:groupadd tomcat``useradd -g tomcat -m -d /home/tomcat tomcat2. 授权 Tomcat 目录:chown -R tomcat:tomcat /usr/local/tomcat3. 以 tomcat 用户运行:su - tomcat -c "/usr/local/tomcat/bin/startup.sh" |
专用用户仅需 Tomcat 目录的读写执行权限,无需系统管理员权限 | |
| Tomcat 默认占用 8080 端口,端口冲突需修改配置 | 端口被占用会导致 Tomcat 启动失败,日志提示Address already in use |
1. 查找占用端口的进程:`ss -tulnp | grep 8080<br>2. 修改端口配置:编辑conf/server.xml,修改<Connector>标签的port属性:<br><Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />`3. 重启 Tomcat 生效 |
1. 避免修改为系统保留端口(1-1024),普通用户运行需用 1024 以上端口;2. 若修改 HTTPS 端口,需同步修改redirectPort |
三、实验:Tomcat + Memcached 实现 Session 会话零丢失
1. 实验步骤
1.1 为 Tomcat 加载 Memcached 相关模块
将 memcached-session-manager 相关 Jar 包复制到 Tomcat 的 lib 目录,并同步到所有 Tomcat 节点(RS1、RS2):
# 解压依赖包压缩包
unzip jar.zip
# 进入解压后的目录
cd jar/
# 复制所有 Jar 包到本地 Tomcat lib 目录
cp * /usr/local/tomcat/lib/
# 将 Jar 包同步到另一台 Tomcat 服务器 RS2
scp * root@172.25.254.20:/usr/local/tomcat/lib/
1.2 安装并配置 Memcached
两台服务器均需执行以下操作,实现 Memcached 部署和可远程访问配置:
1.2.1 安装 Memcached:
dnf install memcached -y
1.2.2 修改 Memcached 配置文件,允许所有地址访问
vim /etc/sysconfig/memcached
# 确保配置内容如下
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 0.0.0.0,::1"
1.2.3 启动 Memcached 并验证端口监听
systemctl start memcached
# 验证 11211 端口监听
netstat -antluple | grep memcached
Memcached 启动成功标识 :终端输出包含 0.0.0.0:11211 和 ::1:11211 的 LISTEN 状态。
1.3 配置 Tomcat 关联 Memcached
修改 Tomcat 核心配置文件 conf/context.xml,添加 Memcached 会话管理配置,RS1 和 RS2 配置仅 ** failoverNodes ** 不同。
1.3.1 配置 RS1的 context.xml:
[root@RS1 ]# vim /usr/local/tomcat/conf/context.xml
# 在 <Context> 标签内添加以下配置,完整文件内容如下
<Context>
<!-- 原有监控资源配置,保留不变 -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Memcached 会话管理核心配置 -->
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.25.254.10:11211,n2:172.25.254.20:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
1.3.2 配置 RS2的 context.xml:
[root@RS2 ]# vim /usr/local/tomcat/conf/context.xml
# 仅修改 failoverNodes 为 n2,其余配置与 RS1 一致
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.25.254.10:11211,n2:172.25.254.20:11211"
failoverNodes="n2" # 仅此处与 RS1 不同
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
1.3.3 重启两台服务器的 Tomcat,使配置生效
systemctl restart tomcat.service
2. 实验结果

3. 实验总结
1. Memcached 核心定位
- 类型 :内存型分布式缓存系统,数据存储在内存中,读写性能远高于磁盘存储。
- 核心场景 :适合存储临时、高频访问的数据,如用户会话(Session)、热点缓存数据等,避免频繁访问数据库,大幅提升系统响应速度。
2. 会话管理扩展:MemcachedBackupSessionManager
- 角色 :Tomcat 的第三方会话管理插件,用于实现 Session 的跨节点共享(解决 Tomcat 集群下 Session 不一致问题)。
- 核心能力:将 Tomcat 生成的 Session 数据持久化到 Memcached 集群中,而非仅存储在单个 Tomcat 节点内存,实现会话的高可用与跨节点迁移。
3. 关键配置项解析
| 配置项 | 核心作用 | 配置格式 / 示例 | |||
|---|---|---|---|---|---|
memcachedNodes |
定义 Memcached 集群节点列表,Tomcat 会将 Session 写入这些节点 | 格式:节点名1:IP1:端口1,节点名2:IP2:端口2示例:node1:192.168.1.10:11211,node2:192.168.1.11:11211 |
|||
failoverNodes |
配置故障切换节点,当主 Memcached 节点故障时,自动切换到这些节点,保证会话不丢失 | 格式:节点名3:IP3:端口3示例:node3:192.168.1.12:11211 |
|||
requestUriIgnorePattern |
配置忽略 Session 交互的静态资源路径,减少不必要的 Memcached 读写开销,提升访问速度 | 格式:正则表达式,匹配静态资源(如 .css, .js, .jpg 等)示例:`.*.(png |
jpg | css | js)$` |
4. 核心价值
- 高可用:Session 存储在 Memcached 集群,单节点故障不影响会话可用性。
- 性能优化:内存级读写,避免磁盘 IO 瓶颈;忽略静态资源的 Session 交互,减少缓存压力。
- 集群兼容:支持 Tomcat 集群部署,实现会话跨节点共享,解决负载均衡下的会话粘滞问题。
