一、WEB 技术基础
1.1 HTTP 协议与 B/S 架构
(1)进程 / 线程与网络通信基础
操作系统通过多进程 + 多线程 充分利用硬件资源:进程是资源分配的基本单位,线程是 CPU 调度的基本单位,多线程实现程序并行执行,让单台主机可作为服务器为多个客户端提供计算服务。跨主机进程间通信依赖网络编程 ,最核心的编程接口是Socket(套接字),类比 "插座",通信分为两端:
- 服务器端:被动接收请求,提供计算和数据服务;
- 客户端:主动发起计算 / 数据请求。
(2)C/S 编程模式
基于 Socket 实现的Client/Server(C/S) 是底层编程模式,基于传输层 TCP/UDP 协议,开发的程序需单独安装客户端,典型案例 :QQ、迅雷、云音乐、云盘、Foxmail、Xshell。核心特点:底层通信、客户端与服务端强耦合、定制化程度高,但开发和维护成本高。
(3)B/S 编程模式的诞生与发展
- 基础诞生 :1990 年HTTP 协议 + 浏览器 诞生,在应用层 通过文本格式跨网络传输数据,浏览器将服务器返回的 HTML 渲染为可视化页面,正式诞生网页开发。
- 核心逻辑:网页是存储在 WEB 服务器的文本文件,浏览器通过 URL 发起 HTTP 请求,WEB 服务器根据 URL 读取对应 HTML 文件,封装为 HTTP 响应报文返回给浏览器。
- 静态网页阶段 :早期网页仅由 HTML、CSS 制作,核心能力是静态展示 (文字、图片)和超链接跳转,无动态交互能力。
- 动态网页的探索
- 浏览器端动态:网景公司 1995 年推出JavaScript (初期名 LiveScript,借 Java 名气更名),通过浏览器 JS 引擎执行,实现网页元素动态变化;微软 ActiveX、SUN Applet 也能实现浏览器端代码执行,但存在严重安全漏洞,未成为主流。
- 服务器端动态:为规避浏览器端安全问题,诞生CGI(通用网关接口) ,实现 URL 直接映射服务器端脚本程序,脚本可查询数据库并动态生成页面内容,这是动态网页技术的核心开端。
- B/S 模式成型 :在 CGI 基础上,衍生出 ASP、PHP、JSP 等WEB 后端编程技术 (代码运行在服务器端),与运行在浏览器端的WEB 前端编程技术 (HTML、CSS、JS)结合,形成Browser/Server(B/S) 编程模式,无需安装客户端,通过浏览器即可访问。
1.2 前端三大核心技术
(1)HTML(超文本标记语言)
-
核心定位 :非编程语言,是网页的结构骨架,用于定义网页的内容和布局。
-
超文本含义:超出纯文本范畴,可描述文本格式(颜色、大小、字体),嵌入图片、音频、视频等非文本内容。
-
组成结构 :由各类标签组成,标签各司其职(布局、文字、图片、链接等),一个 HTML 文件 = 格式标签 + 业务数据。
-
核心依赖 :需浏览器解析渲染,才能将标签转化为可视化页面;HTTP 协议实现超文本的网络传输与共享。
-
基础示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body>老李老李出门见喜
</body> </html>
(2)CSS(层叠样式表)
- 诞生背景 :HTML 本身的样式能力有限,为实现复杂样式需嵌套大量标签,导致 HTML 文件臃肿冗余 ,CSS 应运而生,专门负责网页的样式美化。
- 标准发展 :1994 年 W3C 成立,CSS 设计小组加入并主导标准研发;1996 年 12 月发布CSS 1.0 (基础样式能力);1998 年 5 月发布CSS 2.0 (完善布局、浮动、定位等能力);CSS 3.0 :采用模块化设计,在 CSS 2 基础上逐个模块升级(如动画、弹性布局、网格布局),模块陆续发布,至今仍在更新。
- 核心问题 :浏览器兼容性,不同浏览器的渲染引擎(如 Chrome 的 Blink、Firefox 的 Gecko、IE 的 Trident)对 CSS 标准的支持程度不同,导致同一套 CSS 代码在不同浏览器中显示效果不一致。
(3)JavaScript(JS)
- 核心属性 :动态、弱类型、解释型脚本语言 ,是网页的行为引擎,实现网页的交互、动态效果、数据处理等功能,与 HTML、CSS 并称 WEB 前端三大核心技术,兼容所有主流浏览器。
- 发展历程 :1994 年:网景公司发布 Netscape Navigator 浏览器,占据主流市场;1995 年 9 月:网景推出 LiveScript,12 月更名为JavaScript ,借 Java 的品牌效应推广;1997 年:网景、微软、SUN 等企业联合 ECMA(欧洲计算机制造商协会)制定ECMAScript 标准 ,JS 和微软的 JScript 均成为该标准的实现,解决语言碎片化问题;2008 年:Chrome 浏览器发布V8 引擎 (C++ 开发),颠覆 JS 执行方式 ------本地编译执行 (而非传统解释执行),大幅提升运行效率,堪比本地二进制程序;2009 年:基于 V8 引擎的Node.js 诞生,推出npm(Node 包管理器) ,构建了庞大的开源库生态,让 JS 突破浏览器限制,成为服务器端编程语言 ,实现前后端通用(目前唯一的前后端通用语言)。
(4)同步与异步交互(WEB 交互核心)
① 同步交互
- 核心逻辑 :用户发起请求后,浏览器阻塞等待 服务器响应,响应完成后返回全新页面,即使仅需更新少量内容,也需重新渲染整个页面。
- 典型问题:用户体验差(页面刷新等待)、资源浪费(带宽、浏览器渲染资源),例如注册页面仅密码不一致,提交后整个页面刷新,所有输入项需重新填写。
- 本质:请求与响应一一对应,单线程阻塞执行。
② 异步交互
- 核心逻辑 :用户发起请求后,浏览器不阻塞 ,可继续操作,服务器仅返回需要更新的少量数据 ,浏览器仅局部更新页面,无需整体刷新。
- 技术演进 :1996 年:微软推出iframe 标签 ,实现页面局部异步加载,是早期异步雏形;1999 年:微软推出 ActiveX 插件,内置XMLHttpRequest 对象 ,实现异步数据传输,虽插件笨重,但该对象成为核心基础;核心技术:Ajax(Asynchronous JavaScript And XML) ,1998 年起源于微软 Outlook Web Access 团队,是技术组合(非发明),核心是通过 JS 调用 XMLHttpRequest 对象,实现后台与服务器的少量数据交换。
- Ajax 核心特点 :无需刷新整个页面,仅局部更新;异步通信,不阻塞浏览器操作;早期基于 XML 数据格式,目前主流使用JSON (轻量、易解析);实现前后端彻底分离,改变传统开发模式(前端专注页面,后端专注接口)。
二、WEB 框架体系
2.1 WEB 资源与访问方式

WEB 资源分为静态资源 (HTML、CSS、JS、图片、视频)和动态资源 (数据库查询结果、业务逻辑计算结果),对应不同的服务器存储和访问方式,主要分为PC / 移动端浏览器访问 和手机 App 访问 两类,核心架构包含:静态 WEB 服务器、图片服务器、业务服务器、数据库服务器。
(1)PC / 移动端浏览器访问
- 从静态 WEB 服务器请求 HTML、CSS、JS 等文件,浏览器接收后解析渲染;
- 从图片服务器请求图片、视频等媒体资源,嵌入页面展示;
- 从业务服务器 发起动态请求,业务服务器访问数据库服务器获取数据,处理后返回动态内容至浏览器。
(2)手机 App 访问
- App内置 HTML、JS 文件,无需从静态 WEB 服务器下载,减少网络请求,解决现代前端 JS 文件过大 / 过多的问题;
- 按需从图片服务器 请求媒体资源,从业务服务器请求动态数据;
- 核心依赖业务服务器集群,满足多样化的客户需求,单台业务服务器无法支撑高并发和复杂业务。
2.2 后台应用架构(核心:单体架构 vs 微服务架构)

WEB 后台架构经历了单体架构→SOA 架构→微服务架构 的演进,其中微服务架构是 SOA(面向服务架构)的子集,是目前互联网企业的主流架构,核心差异在于功能拆分、部署方式和耦合度。
(1)单体架构(All in One)
① 核心定义
传统单机架构,将一个项目的所有功能模块(如商品、订单、支付、库存、登录、注册)整合在一个工程 中,编译打包为一个包 (jar/war),部署在一台服务器 上,运行为一个进程。
② Java 技术实现
基于JSP+Servlet开发,编译后打包为 war 包,部署在 WEB 应用服务器(Tomcat、Jetty 等)上运行。
③ 扩展方式
水平扩展 :当单台服务器负载不足时,将 war 包复制多份,部署在多台服务器上,通过负载均衡(如 Nginx)实现请求分发。
④ 核心优势
- 开发、测试、部署简单便捷,适合小型项目和初创团队;
- 技术栈统一,无需处理分布式问题,开发成本低;
- 调试方便,单进程运行,问题定位快速。
⑤ 核心劣势
- 模块耦合度极高 ,单个模块故障可能导致全站不可用;
- 模块修改、Bug 修复、版本升级需停止整个服务 ,重新打包部署,不支持快速迭代,无法满足互联网业务的快速更新需求;
- 大型项目中,代码量庞大,维护和分工难度大,多人协作开发易产生冲突;
- 水平扩展成本高,需复制整个应用,资源利用率低。
⑥ 适配 WEB 应用服务器
- 开源:Tomcat、Jetty、Glassfish(轻量级,适合中小型项目);
- 商用:Weblogic、Websphere、Jboss(重量级,功能完善,适合大型企业项目,需付费)。
(2)微服务架构(Microservices)
① 核心定义
将传统一站式单体应用,按照业务边界 拆分为多个独立的微服务 ,每个微服务仅负责一个单一的业务功能 (如订单服务、支付服务、商品服务),各服务可独立开发、测试、部署、启动 / 销毁,属于分布式架构。
② 核心特征
- 服务松耦合,业务边界清晰,无代码依赖;
- 每个服务可使用独立的技术栈(如 Java、Python、Go、PHP),独立的数据库(也可共用统一数据库);
- 服务间通过轻量级通信机制 交互,主流为基于 HTTP 的 RESTful API;
- 服务可独立扩展,根据业务压力仅扩展高并发服务(如秒杀场景仅扩展订单服务),资源利用率高。
③ 对研发团队的影响
改变传统水平团队架构 (前端、后端、DBA、测试分属不同团队,按技术分工),转向垂直团队架构 (按业务分工,如订单团队、支付团队、用户团队),每个团队负责一个微服务的全生命周期(开发、测试、部署、运维),实现 "让专业的人干专业的事"。企业实际情况 :不会绝对拆分,多为水平 + 垂直的混合架构,兼顾技术复用和业务独立。
④ 核心优势
- 服务内聚性强,代码量少,易理解、易修改、易维护;
- 小团队(2-5 人)可独立开发一个微服务,开发效率高,团队协作冲突少;
- 服务独立部署 ,修改或升级无需停止其他服务,支持快速迭代;
- 支持多语言开发,可根据业务场景选择最优技术栈(如大数据场景用 Python,高并发场景用 Go);
- 易与第三方系统集成,可通过持续集成工具(Jenkins、Hudson、Bamboo)实现自动化部署;
- 前后端彻底分离,微服务仅负责业务逻辑和数据接口,不涉及 HTML/CSS 等前端内容;
- 服务可独立存储,根据业务需求设计数据库,提升数据安全性和性能。
⑤ 核心劣势
- 架构复杂度提升,增加开发、测试、运维、监控的成本(需维护多个服务、多个数据库);
- 分布式问题突出,需解决服务注册 / 发现、服务治理、分布式事务、数据一致性等问题,引入异步补偿机制;
- 对开发人员和运维人员的技术能力要求高,需掌握分布式、微服务框架、容器化(Docker/K8s)等技术;
- 不适合小型项目,盲目拆分会导致架构过度设计,维护成本远高于开发成本。
⑥ 常见微服务框架
| 框架 | 核心定位 | 通信协议 | 服务治理 | 适用场景 |
|---|---|---|---|---|
| Dubbo | 高性能 Java RPC 框架 | RPC(自定义) | Zookeeper | 纯 Java 技术栈、高并发场景 |
| Spring Cloud | 完整微服务解决方案 | HTTP/RESTful | Eureka/Nacos | 多语言技术栈、分布式场景 |
✅ Dubbo
- 阿里开源,后捐赠给 ASF(Apache 软件基金会),成为 Apache 顶级项目;
- 核心能力:将单体程序拆分为多个功能服务模块,模块间通过高性能 RPC 协议通信,比 HTTP 协议效率更高;
- 服务治理:基于Zookeeper实现服务注册、服务发现、负载均衡、服务熔断、服务降级。
✅ Spring Cloud
- 基于 Spring 生态的微服务全家桶 ,是 Dubbo 的超集,提供完整的微服务解决方案;
- 核心能力:将单体应用拆分为粒度更细的单一功能服务,模块间通过HTTP/RESTful API通信,兼容性更强;
- 生态丰富:包含 Eureka(服务注册)、Ribbon(负载均衡)、Hystrix(服务熔断)、Feign(远程调用)、Config(配置中心)、Sleuth(链路追踪)等组件。
(3)单体架构与微服务架构核心对比

| 对比维度 | 单体架构 | 微服务架构 |
|---|---|---|
| 工程结构 | 一个工程,所有代码整合 | 多个独立工程,按业务拆分 |
| 部署方式 | 一个包(jar/war),一个进程 | 多个包,多个独立进程 |
| 耦合度 | 模块高耦合,代码相互依赖 | 服务松耦合,无代码依赖,业务边界清晰 |
| 扩展方式 | 水平扩展,复制整个应用 | 独立扩展,仅复制高并发服务 |
| 数据库 | 单一数据库,所有模块共用 | 各服务可独立数据库,也可共用 |
| 技术栈 | 必须统一 | 支持多语言、多技术栈 |
| 部署成本 | 低,单包部署 | 高,多服务独立部署 |
| 维护成本 | 小型项目低,大型项目极高 | 小型项目高,大型项目低 |
| 迭代速度 | 慢,需整体重启 | 快,服务独立更新 |
| 分布式问题 | 无,单机运行 | 有,需解决服务治理、分布式事务等 |
| 团队架构 | 水平架构,按技术分工 | 垂直架构,按业务分工 |
| 适用场景 | 小型项目、初创团队、传统企业项目 | 大型互联网项目、高并发场景、快速迭代业务 |
三、Tomcat 核心详解
3.1 Tomcat 基础认知
(1)官方定义
Apache Tomcat 是免费、开源的轻量级 WEB 应用服务器 ,由 Apache 软件基金会维护,适用于中小型系统 和并发访问用户不多的场景,是目前最主流的 Java WEB 应用服务器。
(2)核心能力
- 具备处理静态 HTML 页面的能力;
- 是标准的Servlet 容器 和JSP 引擎,支持 JSP+Servlet 开发的 Java WEB 项目部署;
- 支持 HTTP/1.1 协议,兼容主流浏览器;
- 支持虚拟主机、负载均衡、集群部署等高级功能。
(3)发展历程
- 起源:源于SUN 公司 的 Servlet 参考实现项目Java Web Server,由 James Duncan Davidson 开发;
- 1999 年:SUN 将项目捐赠给Apache 软件基金会(ASF),与 ASF 的 JServ 项目合并,开源成为 Apache 顶级项目,命名为 Tomcat;
- 1999 年:发布Tomcat 3.0 ,实现Servlet 2.2 和JSP 1.1规范,是第一个正式版本;
- Tomcat 4.x:内置Catalina(Servlet 容器) 和Jasper(JSP 引擎),成为核心架构,沿用至今;
- 版本现状:正式版已更新至 9.0.x,企业主流使用 7.x 和 8.x 版本(稳定性高、生态完善)。
(4)Java EE 规范支持
Tomcat仅实现了 Java EE 规范中与 Servlet、JSP 相关的类库 ,是Java EE 的不完整实现 ,未实现 EJB、JMS、JTA 等企业级规范,因此被称为轻量级应用服务器;若需使用完整 Java EE 规范,需使用 Weblogic、Websphere 等重量级商用服务器。
(5)官方资源
- 官网:http://tomcat.apache.org/
- 8.5.x 官方文档:https://tomcat.apache.org/tomcat-8.5-doc/index.html
- 帮助文档:https://cwiki.apache.org/confluence/display/tomcat/、https://cwiki.apache.org/confluence/display/tomcat/FAQ
3.2 Tomcat 安装(Linux 环境,CentOS 为例)
Tomcat 基于 Java 开发,运行前必须先安装Java 环境(JDK),推荐使用 JDK1.8(兼容性最好,与 Tomcat 7/8/9 完美匹配)。
步骤 1:安装并验证 Java 环境
# 1. 安装OpenJDK 1.8(开源免费,企业主流)
[root@tomcat ~]# yum install java-1.8.0-openjdk.x86_64 -y
# 2. 验证Java版本,确认安装成功
[root@tomcatA ~]# java -version
# 预期输出:
openjdk version "1.8.0_402"
OpenJDK Runtime Environment (build 1.8.0_402-b06)
OpenJDK 64-Bit Server VM (build 25.402-b06, mixed mode)
# 3. 查看Java可执行文件路径
[root@tomcatA ~]# which java
# 预期输出:/usr/bin/java
# 4. 查看Java软链接指向的实际路径(JRE目录)
[root@tomcatA ~]# ll /usr/bin/java
# 预期输出:lrwxrwxrwx 1 root root 22 Jul 30 10:41 /usr/bin/java -> /etc/alternatives/java
# 5. 进入JRE运行环境目录,验证文件完整性
[root@tomcatA ~]# cd /etc/alternatives/jre
[root@tomcatA jre]# ls
# 预期输出:ASSEMBLY_EXCEPTION bin lib LICENSE THIRD_PARTY_README
步骤 2:安装并启动 Tomcat
# 1. 从Apache官网下载Tomcat安装包(以9.0.107为例),上传至Linux服务器/root目录
# 2. 解压安装包至/usr/local/(Linux常用软件安装目录)
[root@tomcatA ~]# tar zxf apache-tomcat-9.0.107.tar.gz -C /usr/local/
# 3. 重命名解压目录,简化操作(可选,推荐)
[root@tomcatA ~]# cd /usr/local/
[root@tomcatA local]# mv apache-tomcat-9.0.107/ tomcat
# 4. 进入Tomcat的bin目录(存放启动/停止脚本)
[root@tomcatA local]# cd tomcat/bin/
# 5. 启动Tomcat(./startup.sh为Linux启动脚本,catalina.bat为Windows脚本)
[root@tomcatA bin]# ./startup.sh
# 预期输出,确认启动成功:
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
步骤 3:验证 Tomcat 启动
# 1. 查看Tomcat端口(默认8080,TCP6协议)
[root@tomcat ~]# netstat -antlupe | grep java
# 预期输出:tcp6 0 0 :::8080 :::* LISTEN 0 68636 32887/java
# 2. 浏览器访问Tomcat默认页面,验证是否可访问
# 访问地址:http://服务器IP:8080
# 若页面显示"Apache Tomcat/9.0.91"及欢迎信息,说明启动成功

步骤 4:配置 Tomcat 为系统服务(开机自启,推荐)
默认通过./startup.sh启动的 Tomcat,重启服务器后会停止,需配置为systemd 系统服务,实现开机自启和便捷的服务管理。
# 1. 生成Tomcat配置文件,指定JAVA_HOME(JRE目录)
[root@tomcat ~]# vim /usr/local/tomcat/conf/tomcat.conf
# 写入以下内容:
JAVA_HOME=/etc/alternatives/jre
# 2. 生成systemd服务文件(/lib/systemd/system/为系统服务默认目录)
[root@tomcat ~]# 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 # 开机自启级别
# 3. 创建tomcat用户和用户组(禁止登录,仅用于运行服务)
[root@tomcatB bin]# useradd -s /sbin/nologin -M tomcat
# 4. 给Tomcat安装目录赋予tomcat用户/组的权限
[root@tomcatB bin]# chown tomcat.tomcat /usr/local/tomcat/ -R
# 5. 重新加载systemd配置,使服务文件生效
[root@tomcatB ~]# systemctl daemon-reload
# 6. 启动Tomcat并设置开机自启
[root@tomcatB ~]# systemctl enable --now tomcat
# 7. 验证服务状态
[root@tomcatB ~]# systemctl status tomcat
# 显示active (running)即为成功
3.3 Tomcat 文件结构与核心目录
Tomcat 的安装目录结构清晰,各目录各司其职,核心目录共 7 个,掌握目录功能是配置和部署 Tomcat 的基础,默认安装目录:/usr/local/tomcat。
(1)完整目录列表
[root@tomcat ~]# ls /usr/local/tomcat/
bin BUILDING.txt conf CONTRIBUTING.md lib LICENSE logs NOTICE README.md RELEASE-NOTES RUNNING.txt temp webapps work
(2)核心目录详细说明
| 目录名 | 英文全称 | 核心功能与详细说明 |
|---|---|---|
| bin | Binary | 存放 Tomcat启动、停止、配置等脚本文件,核心脚本:・startup.sh/shutdown.sh:Linux 启动 / 停止脚本・catalina.sh:核心运行脚本(startup/shutdown 最终调用它)・configtest.sh:配置文件检测脚本・version.sh:版本查看脚本 |
| conf | Configuration | 存放 Tomcat核心配置文件,是 Tomcat 配置的核心目录,关键文件:・server.xml:全局核心配置(端口、连接器、引擎、虚拟主机)・context.xml:全局应用上下文配置・web.xml:全局 WEB 应用配置・tomcat-users.xml:用户权限配置(管理后台)・catalina/:Catalina 容器配置目录 |
| lib | Library | 存放 Tomcat 运行所需的所有 Java 类库(jar 包) ,包括 Servlet、JSP 核心包、第三方依赖包;注意:放入此目录的 jar 包对所有部署在 Tomcat 上的应用生效 |
| logs | Logs | 存放 Tomcat所有日志文件 ,关键日志:・catalina.out:Tomcat 核心运行日志(包含启动日志、运行异常日志)• localhost.log:本地主机访问日志・localhost_access_log.*.txt:访问日志(记录所有 HTTP 请求)・manager.log/host-manager.log:管理后台日志 |
| webapps | Web Applications | Tomcat 的应用部署默认目录,相当于 Nginx 的 root 目录;・将 Java WEB 项目的 war 包或解压后的目录放入此目录,Tomcat 会自动部署;・内置默认应用:ROOT(默认首页)、manager(管理后台)、host-manager(虚拟主机管理) |
| temp | Temporary | 存放 Tomcat 运行过程中产生的临时文件,由 JVM 自动创建和清理,可手动删除 |
| work | Workspace | 存放 Tomcat 对JSP 编译后的 class 文件 (JSP 最终会被编译为 Servlet 执行);优化建议:生产环境提前预热访问,让 JSP 提前编译,避免首次访问卡顿;删除此目录,Tomcat 重启后会重新编译 JSP |
四、结合反向代理实现 Tomcat 部署
Tomcat 的standalone(单机独立运行)模式 存在明显缺陷:静态资源处理性能低、并发能力有限、易单点故障,因此生产环境不推荐单独使用 Tomcat ,主流方案是结合 Nginx/Apache 做反向代理,实现 "静态资源由代理服务器处理,动态请求由 Tomcat 处理" 的分工,同时可实现 Tomcat 集群负载均衡。
4.1 Tomcat 常见部署方式

根据业务规模和并发需求,Tomcat 部署方式分为 4 种,复杂度由低到高,适用于不同场景:
(1)Standalone Tomcat(单机独立运行)
- 架构:Tomcat 直接暴露给用户,接收所有 HTTP 请求,同时处理静态资源和动态请求;
- 优点:架构简单,无额外依赖;
- 缺点:静态资源处理性能低、并发能力有限、单点故障;
- 适用场景:开发环境、测试环境,生产环境绝对不推荐。
(2)单机反向代理部署
- 架构:代理服务器(Nginx/Apache)+ 单台 Tomcat,代理服务器作为前端,接收所有请求;
- 分工:静态资源(HTML、CSS、JS、图片) 由代理服务器直接响应,动态请求(JSP、Servlet) 通过反向代理转发至 Tomcat 处理;
- 主流组合:・LNMT :Linux + Nginx + MySQL + Tomcat(企业主流,Nginx 静态处理性能远高于 Apache);・LAMT:Linux + Apache + Httpd + MySQL + Tomcat;
- 优点:提升静态资源处理性能,降低 Tomcat 负载;
- 缺点:Tomcat 单点故障,仍无法支撑高并发;
- 适用场景:中小型企业,低并发业务场景。
(3)多机反向代理部署
- 架构:Nginx(负载均衡)+ 多台 Tomcat 集群,Nginx 作为前端反向代理和负载均衡器,将动态请求分发至多台 Tomcat;
- 核心优势:解决单点故障,提升并发处理能力,可水平扩展 Tomcat 节点;
- 适用场景:中大型互联网企业,中高并发业务场景(如电商、社交、资讯)。
(4)多机多级反向代理部署
- 架构:多层 Nginx + Tomcat 集群,第一层 Nginx 做入口代理,第二层 Nginx 做负载均衡,分发至 Tomcat 集群;
- 核心优势:架构更灵活,可实现地域级、机房级的负载均衡,提升架构的高可用性和扩展性;
- 主流组合:LNNMT:Linux + Nginx + Nginx + MySQL + Tomcat;
- 适用场景:大型互联网企业,高并发、高可用要求的核心业务(如秒杀、双十一、全国性平台)。
4.2 Nginx 单机反向代理 Tomcat(实操配置)

核心原理:通过 Nginx 的proxy_pass指令,将JSP 动态请求 转发至 Tomcat,静态资源由 Nginx 本地直接响应,实现动静分离。
前提条件
- Linux 服务器已安装 Nginx(参考 Nginx 官方安装文档);
- Tomcat 已启动,监听 8080 端口,可正常访问;
- 配置 Nginx 的域名解析(如lee.timinglee.org),或直接使用 IP 访问。
配置步骤
# 1. 进入Nginx的虚拟主机配置目录(企业主流配置方式,避免修改主配置文件)
[root@Nginx ~]# cd /usr/local/nginx/conf.d/
# 2. 创建/编辑虚拟主机配置文件(vhosts.conf,名称自定义)
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
# 3. 写入配置内容,实现动静分离和反向代理
server {
listen 80; # 监听80端口
server_name lee.timinglee.org; # 域名/服务器IP
# 静态资源根目录(存放HTML、CSS、JS、图片等)
root /webdata/nginx/timinglee.org/lee;
index index.html index.htm;
# 访问日志和错误日志
access_log /var/log/nginx/lee_access.log main;
error_log /var/log/nginx/lee_error.log warn;
# 动态JSP请求,转发至Tomcat
location ~ \.jsp$ {
proxy_pass http://172.25.254.10:8080; # Tomcat的IP+端口
# 反向代理优化配置(推荐添加)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
}
}
# 4. 检测Nginx配置文件语法是否正确
[root@Nginx ~]# /usr/local/nginx/sbin/nginx -t
# 显示"nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful"即为正确
# 5. 重新加载Nginx配置,使配置生效(无需重启,不中断服务)
[root@Nginx ~]# /usr/local/nginx/sbin/nginx -s reload
测试验证
- 在 Nginx 的静态资源根目录
/webdata/nginx/timinglee.org/lee放入静态 HTML 文件,访问http://lee.timinglee.org,验证静态资源由 Nginx 响应; - 在 Tomcat 的 webapps 目录部署 JSP 项目,访问
http://lee.timinglee.org/test.jsp,验证 JSP 请求被转发至 Tomcat 处理,实现动静分离。
4.3 Tomcat 负载均衡实现(Nginx + 多 Tomcat,实操配置)
当单台 Tomcat 无法支撑高并发时,需部署Tomcat 集群 ,通过 Nginx 实现负载均衡,将请求分发至多台 Tomcat,提升并发能力和高可用性。
4.3.1 核心问题:HTTP 无状态与 Session 一致性
负载均衡的核心痛点是Session 一致性问题 ,根源在于HTTP 协议的无状态性:
(1)HTTP 协议的三大特性
- 无状态 :服务器无法识别两次 HTTP 请求的关联,即使来自同一浏览器,服务器也视为独立请求;为解决此问题,诞生了Cookie+Session 机制 :
- 浏览器第一次请求时,服务器生成SessionID(随机唯一值),创建 Session 对象存储用户信息;
- 服务器将 SessionID 通过 Cookie 返回给浏览器,浏览器保存在本地;
- 后续请求时,浏览器携带 SessionID,服务器通过 SessionID 找到对应的 Session 对象,实现用户状态保持。
- 注意:Session 默认存储在服务器内存中,未持久化时易丢失,且有过期时间(默认 30 分钟);关闭浏览器、更换浏览器会丢失 SessionID,需重新生成。
- 有连接 :HTTP 基于TCP 协议 ,是面向连接的协议,需通过三次握手 建立连接,四次挥手断开连接。
- 短连接(HTTP1.1 之前) :一请求一连接,TCP 连接创建和销毁的成本高,服务器压力大;HTTP1.1 引入keep-alive(长连接),默认开启,一个 TCP 连接可处理多个 HTTP 请求,保持一段时间后断开,大幅降低服务器压力。
(2)负载均衡的 Session 问题
Nginx 将请求调度至不同的 Tomcat 节点 时,由于 Session 存储在单个 Tomcat 的内存中,其他 Tomcat 节点无此 SessionID,导致会话失效(如用户登录后,再次请求被调度至其他 Tomcat,需重新登录)。
(3)Session 问题的临时解决方案
Nginx 提供两种调度算法,可临时解决 Session 一致性问题:
- ip_hash :基于客户端 IP 地址 进行哈希计算,将同一 IP 的所有请求固定调度至同一台 Tomcat ,实现 Session 保持;
- 优点:配置简单,无需修改 Tomcat;
- 缺点:若 Tomcat 节点故障,该 IP 的用户 Session 丢失;且同一局域网的用户(同一公网 IP)会被调度至同一 Tomcat,导致负载不均。
- hash $cookie_JSESSIONID :基于浏览器的 SessionID 进行哈希计算,将同一 SessionID 的请求固定调度至同一台 Tomcat;
- 优点:比 ip_hash 更精准,负载更均衡;
- 缺点:若 Tomcat 节点故障,Session 仍会丢失。
注意 :以上两种方法为临时解决方案 ,生产环境需使用Session 共享技术(如 Memcached、Redis)实现持久化,从根本上解决 Session 一致性问题。
4.3.2 Nginx 配置 Tomcat 负载均衡(实操)
核心指令:upstream ,定义 Tomcat 集群节点,通过调度算法实现负载均衡;再通过proxy_pass将请求转发至 upstream 定义的集群。
配置步骤
# 1. 编辑Nginx虚拟主机配置文件
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
# 2. 写入配置内容,定义Tomcat集群并实现负载均衡
# 第一步:定义Tomcat集群,命名为tomcat(自定义)
upstream tomcat {
# 调度算法:ip_hash 或 hash $cookie_JSESSIONID(二选一)
# ip_hash;
hash $cookie_JSESSIONID;
# Tomcat集群节点,格式:server IP:端口;
server 172.25.254.10:8080; # Tomcat1
server 172.25.254.20:8080; # Tomcat2
# 可添加更多节点,支持权重配置:server 172.25.254.30:8080 weight=2;(权重2,调度概率更高)
}
# 第二步:配置服务器,将动态请求转发至Tomcat集群
server {
listen 80;
server_name lee.timinglee.org;
root /webdata/nginx/timinglee.org/lee;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
try_files $uri $uri.html $uri/index.html /error/default.html;
# 动态JSP请求转发至Tomcat集群
location ~ \.jsp$ {
proxy_pass http://tomcat; # 指向upstream定义的集群名称
# 反向代理优化配置(必须添加)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# 3. 检测配置语法,重新加载Nginx
[root@Nginx ~]# /usr/local/nginx/sbin/nginx -t
[root@Nginx ~]# /usr/local/nginx/sbin/nginx -s reload
测试验证
- 启动所有 Tomcat 节点,确保均可正常访问;
- 浏览器访问
http://lee.timinglee.org/test.jsp,多次刷新,查看 Nginx 的访问日志,验证请求被分发至不同 Tomcat(若未用 ip_hash/hash); - 登录测试,验证 Session 是否保持(若使用 ip_hash/hash,登录后多次请求不会重新登录)。
五、Memcached 核心详解(Tomcat Session 共享基础)

为从根本上解决 Tomcat 集群的 Session 一致性问题,需使用分布式缓存 将 Session 持久化,Memcached是轻量级分布式内存缓存系统,是 Tomcat Session 共享的主流选择之一。
5.1 Memcached 基础认知
(1)官方定义
Memcached 是免费、开源、基于 Key-Value 的分布式内存缓存系统,由 Danga Interactive 开发,核心作用是将热点数据缓存至内存,提升数据读取速度,降低数据库压力。
(2)核心特性
- 纯内存存储:数据全部存储在内存中,读取速度极快(毫秒级),无磁盘 IO 开销;
- 无持久化能力 :不支持 RDB、AOF 等持久化方式,服务器重启后数据丢失;可通过集群同步实现数据一致性,避免单点丢失;
- 支持序列化 :仅能存储可序列化的数据类型(如字符串、对象、数组),非序列化数据无法存储;
- 内存限制 :单个存储对象的最大大小为 1M ,超过 1M 的数据可通过客户端压缩 或拆分为多个 Key 存储;
- 高性能 IO :基于libevent 库实现高效的 IO 多路复用,libevent 封装了 Linux 的 epoll、BSD 的 kqueue 等底层事件处理接口,即使高连接数下仍能保持高性能;
- 跨平台、跨语言:支持 Linux、BSD、Solaris 等操作系统,支持 Java、C、Python、PHP、C# 等几乎所有开发语言;
- 简单的内存管理 :存储数据时,自动申请1MB 的内存块 ,称为slab(页),按 slab 管理内存,避免内存碎片。
(3)核心适用场景
- 热点数据缓存:将数据库的热点查询结果缓存至 Memcached,降低数据库压力;
- Tomcat Session 共享 :将 Tomcat 的 Session 对象缓存至 Memcached 集群,实现多 Tomcat 节点的 Session 一致性(最核心场景);
- 计数器缓存:如商品浏览量、点赞数、访问量等高频更新的计数器。
(4)与 Redis 的核心区别(简版)
| 特性 | Memcached | Redis |
|---|---|---|
| 持久化 | 不支持 | 支持 RDB、AOF、混合持久化 |
| 数据类型 | 仅 Key-Value 字符串 | 支持 String、List、Hash、Set 等多种类型 |
| 单个对象大小 | 最大 1M | 最大 512M |
| 内存管理 | 预分配 slab,简单高效 | 动态分配,支持内存淘汰策略 |
| 集群能力 | 原生集群同步,简单 | 支持主从、哨兵、集群(Redis Cluster) |
| 适用场景 | 简单缓存、Session 共享 | 复杂缓存、分布式锁、消息队列、持久化存储 |
(5)官方资源
5.2 Memcached 安装与启动(Linux CentOS 为例)
Memcached 可通过 yum 快速安装,配置简单,默认端口11211。
步骤 1:安装 Memcached
# 1. 通过yum安装Memcached(开源免费,官方源已收录)
[root@tomcat ~]# yum install memcached -y
# 2. 查看Memcached版本,确认安装成功
[root@tomcat ~]# memcached -V
步骤 2:配置 Memcached
Memcached 的配置文件为/etc/sysconfig/memcached,可配置端口、运行用户、最大连接数、缓存大小等核心参数。
# 编辑配置文件
[root@tomcat ~]# vim /etc/sysconfig/memcached
# 核心配置参数,按需修改(默认配置即可满足大部分场景)
PORT="11211" # 监听端口,默认11211
USER="memcached" # 运行用户,默认memcached
MAXCONN="1024" # 最大并发连接数,默认1024
CACHESIZE="64" # 缓存大小,单位MB,默认64MB(根据服务器内存调整)
OPTIONS="-l 0.0.0.0,::1" # 监听地址,0.0.0.0表示监听所有IP,支持IPv4和IPv6
步骤 3:启动 Memcached 并设置开机自启
# 1. 启动Memcached服务
[root@tomcat ~]# systemctl start memcached
# 2. 设置开机自启
[root@tomcat ~]# systemctl enable --now memcached
# 3. 验证服务状态
[root@tomcat ~]# systemctl status memcached
# 显示active (running)即为成功
# 4. 查看端口监听,确认Memcached正常运行
[root@tomcat ~]# netstat -antlupe | grep memcache
# 预期输出:tcp 0 0 0.0.0.0:11211 :::* LISTEN 980 97815 34711/memcached
5.3 Memcached 基本操作命令
Memcached 提供简单的命令行操作,可通过telnet 或nc 连接 Memcached 服务(默认端口 11211),核心命令共 5 个:set、add、replace、get、delete,涵盖增删改查核心操作。
步骤 1:连接 Memcached
[root@tomcat ~]# telnet localhost 11211
# 成功连接后输出:Trying ::1... Connected to localhost. Escape character is '^]'.
步骤 2:核心命令语法与示例
(1)通用语法(set/add/replace)
command <key> <flags> <expiration time> <bytes>
<value>
- command:操作命令(set/add/replace);
- key:缓存的键,唯一标识,字符串类型;
- flags:整型参数,0 表示不压缩,用于存储键值对的额外信息;
- expiration time:过期时间,单位秒,0 表示永久有效;
- bytes :存储值的字节数,必须与实际值的字节数一致;
- value:存储的值,必须在第二行输入,与 bytes 字节数匹配。
(2)具体命令示例
# 1. add:添加键值对,键不存在时成功,存在则失败(新增)
add leekey 0 60 4 # 键:leekey,不压缩,60秒过期,值4字节
test # 值:test(4字节)
# 成功输出:STORED;失败输出:NOT_STORED
# 2. get:查询键值对,支持多键查询(get key1 key2)
get leekey
# 成功输出:VALUE leekey 0 4 \n test \n END;失败输出:END
# 3. set:设置键值对,键存在则修改,不存在则新增(新增/修改)
set leekey 0 60 5 # 键:leekey,5字节
test1 # 值:test1
# 成功输出:STORED
# 4. replace:替换键值对,键存在则成功,不存在则失败(修改)
replace leekey1 0 60 3
lee
# 成功输出:STORED
# 5. delete:删除键值对
delete leekey
# 成功输出:DELETED;失败输出:NOT_FOUND
# 6. flush_all:清空所有缓存(谨慎使用,生产环境禁止)
flush_all
# 成功输出:OK
# 7. 退出连接:按Ctrl+],再输入quit
^]
quit
六、Tomcat Session 共享实现(Memcached+MSM,生产环境方案)

通过MSM(Memcached Session Manager) 实现 Tomcat Session 的分布式共享 ,将 Tomcat 的 Session 对象序列化后存储至Memcached 集群,所有 Tomcat 节点从 Memcached 读取和写入 Session,从根本上解决 Session 一致性问题,实现高可用。
6.1 MSM 核心认知
(1)MSM 定义
MSM(Memcached Session Manager)是 Tomcat 的Session 管理插件,专门用于将 Tomcat 的 Session 存储至 Memcached,实现多 Tomcat 节点的 Session 共享和高可用。
(2)核心特性
- 支持Tomcat 6.x/7.x/8.x/9.x(覆盖企业主流版本);
- 支持Session 序列化 / 反序列化 ,官方推荐Kryo 序列化框架(高效、轻量,比 Java 原生序列化性能更高);
- 支持Session 备份,可将 Session 同步至多个 Memcached 节点,实现故障转移;
- 支持静态资源忽略,不缓存静态资源的 Session 请求,提升性能;
- 开源免费,项目早期托管在 Google Code,目前托管在Github。
(3)项目地址
- Github:https://github.com/magro/memcached-session-manager
- 官方配置文档:https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration
(4)核心依赖包
MSM 运行需要三类 jar 包,需放入 Tomcat 的lib目录($CATALINA_HOME/lib/,即 /usr/local/tomcat/lib/),所有 Tomcat 节点都需放入相同的 jar 包:
- MSM 核心包:memcached-session-manager-2.3.2.jar、memcached-session-manager-tc9-2.3.2.jar(tc9 对应 Tomcat9,tc8 对应 Tomcat8,依版本调整);
- Kryo 序列化包:kryo-3.0.3.jar、asm-5.2.jar、objenesis-2.6.jar、reflectasm-1.11.9.jar、minlog-1.3.1.jar、kryo-serializers-0.45.jar、msm-kryo-serializer-2.3.2.jar;
- Memcached 驱动包:spymemcached-2.12.3.jar(Java 操作 Memcached 的官方驱动)。
6.2 MSM 安装(核心:放入依赖 jar 包)
步骤 1:下载核心 jar 包
从 MSM 官方 Github 仓库或 Maven 中央仓库(https://mvnrepository.com/)下载上述所有 jar 包,确保版本匹配(推荐 2.3.2 版本,稳定)。
步骤 2:放入 Tomcat 的 lib 目录
将所有下载的 jar 包上传至每台 Tomcat 的/usr/local/tomcat/lib/目录,确保所有 Tomcat 节点的 jar 包一致,无缺失。
# 示例:将jar包放入Tomcat lib目录
[root@tomcat-1 ~]# cp *.jar /usr/local/tomcat/lib/
[root@tomcat-2 ~]# cp *.jar /usr/local/tomcat/lib/
# 赋予权限(可选,避免权限不足)
[root@tomcat-1 ~]# chmod 644 /usr/local/tomcat/lib/*.jar
6.3 Tomcat+MSM+Memcached 配置(实操)
核心配置分为两部分:Tomcat 配置(context.xml) (指定 Memcached 集群、序列化方式)和Nginx 配置(调整调度算法),所有 Tomcat 节点需单独配置,Nginx 仅需一次配置。
前提条件
- 已部署Tomcat 集群(如 2 台:172.25.254.10、172.25.254.20);
- 已部署Memcached 集群(如 2 台:172.25.254.10:11211、172.25.254.20:11211);
- 所有 Tomcat 节点已放入 MSM 核心 jar 包;
- Nginx 已配置 Tomcat 负载均衡。
步骤 1:配置 Tomcat(context.xml)
修改 Tomcat 的核心配置文件/usr/local/tomcat/conf/context.xml,添加 MSM 的 Session 管理器配置,两台 Tomcat 配置仅failoverNodes参数不同(用于 Session 故障转移)。
(1)Tomcat1 配置(172.25.254.10)
[root@tomcat-1 ~]# vim /usr/local/tomcat/conf/context.xml
<!-- 清空原有默认Manager节点,添加以下配置 -->
<Manager
className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
<!-- Memcached集群地址(多个节点用空格分隔) -->
memcachedNodes="n1:172.25.254.10:11211 n2:172.25.254.20:11211"
<!-- 故障转移节点:当前节点故障时,Session切换至n2(Tomcat2) -->
failoverNodes="n2"
<!-- 序列化方式:推荐kryo(高性能) -->
sessionBackupAsync="false"
sessionBackupTimeout="100"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
<!-- 忽略静态资源的Session请求,提升性能 -->
ignorePattern=".*\.(png|gif|jpg|css|js)$"
<!-- Session过期时间(秒),与Tomcat默认一致为1800秒(30分钟) -->
maxInactiveInterval="1800"
<!-- 连接Memcached超时时间(毫秒) -->
operationTimeout="1000"
/>
(2)Tomcat2 配置(172.25.254.20)
[root@tomcat-2 ~]# vim /usr/local/tomcat/conf/context.xml
<!-- 核心区别:failoverNodes指向n1(Tomcat1) -->
<Manager
className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.25.254.10:11211 n2:172.25.254.20:11211"
failoverNodes="n1" <!-- 当前节点故障时,Session切换至n1 -->
sessionBackupAsync="false"
sessionBackupTimeout="100"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
ignorePattern=".*\.(png|gif|jpg|css|js)$"
maxInactiveInterval="1800"
operationTimeout="1000"
/>
关键参数说明
| 参数名 | 作用 | 生产环境建议值 |
|---|---|---|
memcachedNodes |
定义 Memcached 集群节点,格式:节点名:IP:端口 |
多个节点用空格分隔,至少 2 个实现高可用 |
failoverNodes |
故障转移节点,当前 Tomcat 故障时 Session 切换至该节点 | 指向集群中另一台 Tomcat 对应的 Memcached 节点 |
sessionBackupAsync |
是否异步备份 Session | false(同步更可靠,避免 Session 丢失) |
transcoderFactoryClass |
Session 序列化方式 | kryo(性能比 Java 原生高 3-5 倍) |
ignorePattern |
忽略静态资源的 Session 请求 | 包含所有静态资源后缀(png/gif/css/js 等) |
maxInactiveInterval |
Session 过期时间 | 1800 秒(30 分钟),与业务需求匹配 |
重启 Tomcat 使配置生效
# Tomcat1重启
[root@tomcat-1 ~]# systemctl restart tomcat
# Tomcat2重启
[root@tomcat-2 ~]# systemctl restart tomcat
# 验证Tomcat启动状态(无报错则配置生效)
[root@tomcat-1 ~]# systemctl status tomcat
[root@tomcat-2 ~]# systemctl status tomcat
步骤 2:调整 Nginx 配置(移除 IP 绑定,实现真正负载均衡)
由于 Session 已存储在 Memcached 集群,无需再用ip_hash或cookie_JSESSIONID绑定 IP,可使用 Nginx 默认的轮询算法(或加权轮询),实现请求均匀分发。
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
# 修改upstream配置,移除ip_hash/hash指令
upstream tomcat {
# 轮询算法(默认),也可添加weight调整权重(如weight=2)
server 172.25.254.10:8080; # Tomcat1
server 172.25.254.20:8080; # Tomcat2
# 可选:添加down(节点下线)、backup(备用节点)参数
# server 172.25.254.30:8080 backup;
}
server {
listen 80;
server_name lee.timinglee.org;
root /webdata/nginx/timinglee.org/lee;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# 动态请求转发至Tomcat集群
location ~ \.jsp$ {
proxy_pass http://tomcat;
# 必须保留的反向代理头信息(传递真实IP、Host)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# 检测配置语法并重新加载
[root@Nginx ~]# /usr/local/nginx/sbin/nginx -t
[root@Nginx ~]# /usr/local/nginx/sbin/nginx -s reload
步骤 3:验证 Session 共享(生产环境标准验证方法)
(1)编写测试 JSP 页面(所有 Tomcat 节点部署)
在 Tomcat 的webapps/ROOT目录创建session_test.jsp,用于展示当前 Tomcat 节点 IP 和 SessionID:
[root@tomcat-1 ~]# vim /usr/local/tomcat/webapps/ROOT/session_test.jsp
[root@tomcat-2 ~]# vim /usr/local/tomcat/webapps/ROOT/session_test.jsp
<!-- 测试页面内容 -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<title>Tomcat Session共享测试</title>
</head>
<body>
<h1>Session共享测试结果</h1>
<p>当前Tomcat节点IP:<%= request.getLocalAddr() %></p>
<p>当前Tomcat端口:<%= request.getLocalPort() %></p>
<p>SessionID:<%= session.getId() %></p>
<p>Session创建时间:<%= new java.util.Date(session.getCreationTime()) %></p>
<p>Session最后访问时间:<%= new java.util.Date(session.getLastAccessedTime()) %></p>
</body>
</html>
(2)访问测试页面验证
- 浏览器访问
http://lee.timinglee.org/session_test.jsp,记录 SessionID 和当前 Tomcat 节点 IP; - 多次刷新页面,观察 Tomcat 节点 IP 会在 172.25.254.10 和 172.25.254.20 之间切换,但SessionID 始终不变;
- 手动停止其中一台 Tomcat(如 Tomcat1),继续访问页面,请求会自动切换至 Tomcat2,SessionID 仍不变,证明 Session 共享生效。
(3)Memcached 中验证 Session 存储
# 连接Memcached集群,查询Session数据
[root@memcached-1 ~]# telnet 172.25.254.10 11211
Trying 172.25.254.10...
Connected to 172.25.254.10.
Escape character is '^]'.
# 查询所有Session键(以"tomcat_"开头)
stats items # 查看缓存项统计
stats cachedump 1 0 # 列出缓存键(1为slab编号,0为列出所有)
# 输出中会看到类似"tomcat_xxxxxx"的Session键,证明Session已存储至Memcached
# 退出连接
^]
quit
步骤 4:常见问题排查
| 问题现象 | 可能原因 | 解决方案 | ||||
|---|---|---|---|---|---|---|
| Tomcat 启动报错:ClassNotFound MSM | 缺少 MSM 核心 jar 包 | 检查 Tomcat/lib 目录,确保所有 MSM、Kryo、spymemcached jar 包齐全 | ||||
| SessionID 刷新后变化 | Memcached 连接失败 | 检查 Memcached 集群是否启动,Tomcat 配置的 memcachedNodes IP / 端口是否正确 | ||||
| 静态资源加载异常 | ignorePattern 配置错误 | 核对静态资源后缀是否完整,格式为 `.*.(png | gif | jpg | css | js)$` |
| 故障转移不生效 | failoverNodes 配置错误 | 确保 Tomcat1 的 failoverNodes 是 n2,To |