Tomcat

一、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. 实验结果

  1. 核心总结
核心知识点 核心风险 实操落地步骤 关键注意事项
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 集群部署,实现会话跨节点共享,解决负载均衡下的会话粘滞问题。
相关推荐
代码不停2 小时前
自动化测试(java)
java·开发语言·selenium·自动化
鬼手点金4 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
paopaokaka_luck5 小时前
滑雪场管理系统(AI智能助手流式对话,ECharts 运营数据分析、教练、雪具与场地一体化预约,钱包支付退款、订单核销与服务评价)
java·人工智能·spring boot·网络协议·数据分析·echarts
Wang's Blog5 小时前
Java 项目实战: 交友项目 - Dubbo 的内部结构与一次调用的完整链路
java·dubbo
Wang's Blog6 小时前
Java 项目实战: 交友项目 - Dubbo 入门引导
java·dubbo·交友
蜗牛互联网6 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python
SL_staff6 小时前
当规则引擎开始‘懂业务’:JVS-Rules金融风控四大原生能力拆解
java·python·全栈
Shaoshing7 小时前
前缀和与差分
java·数据结构·算法·前缀和·差分
dd聊技术7 小时前
Prompt 从代码常量搬进数据库:改一句话,不用再发一次版
java·后端
ly76897 小时前
Spring Data MongoDB 批量写入实践:BulkOperations 批大小与写关注权衡
java·mongodb·spring·批量写入·bulkoperations·写关注·mongotemplate