【Tomcat】企业级web应用服务器
核心知识点梳理
Web技术基础
C/S与B/S架构
- C/S架构:基于Socket和传输层协议(TCP/UDP),客户端与服务器直接通信,如QQ、迅雷等,需单独安装客户端。
- B/S架构:基于HTTP协议,通过浏览器访问Web服务器,前端(HTML/CSS/JS)运行在浏览器,后端(ASP/PHP/JSP)运行在服务器,无需安装客户端。
前端三大核心技术
- HTML:超文本标记语言,通过标签定义网页结构(如
<html>
<body>
<h1>
),非编程语言。 - CSS:层叠样式表,独立于HTML控制网页样式,支持模块化升级(CSS 3),存在浏览器兼容性问题。
- JavaScript:动态脚本语言,弱类型、解释性执行,V8引擎(Chrome)实现本地编译加速;支持前后端通用开发(Node.js)。
同步与异步技术
- 同步:请求后需等待服务器响应,页面整体刷新(如注册表单重填问题),效率低。
- 异步:基于Ajax技术(核心为
XMLHttpRequest
),可局部更新网页内容,减少带宽浪费,提升用户体验。
Web架构模式
单体架构
- 特点:所有功能(商品、订单、支付等)集成在一个工程,打包为war/jar部署,开发测试简单,但耦合度高,单点故障影响全局。
- 典型实现:Java的JSP/Servlet,部署于Tomcat等容器。
微服务架构
- 特点:按业务拆分独立服务(如用户服务、支付服务),松耦合、可独立部署,支持多语言开发,需解决分布式事务和服务治理问题。
- 主流框架:Dubbo(基于RPC,依赖Zookeeper)、Spring Cloud(基于HTTP RESTful API)。
Tomcat服务器
核心功能:轻量级Web应用服务器,支持Servlet/JSP规范,处理动态网页请求,是Java EE的部分实现(仅包含Servlet/JSP相关类库)。
版本与历史:1999年由Apache基金会接管,当前主流版本为8.x/7.x,最新版本9.0.x,官网:Apache Tomcat® - Welcome!。
文件结构
- bin:启动/停止脚本(如
startup.sh
shutdown.sh
)。 - conf:配置文件(如
server.xml
context.xml
)。 - lib:依赖库文件。
- webapps:应用部署目录(类似Nginx默认发布目录)。
- logs:日志文件。
- work:JSP编译后的字节码文件。
反向代理与负载均衡
反向代理:通过Nginx/Apache作为中间层,转发客户端请求至Tomcat,静态资源(HTML/CSS/JS)由Nginx直接响应,动态资源(JSP)代理至Tomcat。
负载均衡:通过Nginx的upstream
模块分发请求至多台Tomcat,常见策略:
ip_hash
:基于客户端IP分配服务器(可能导致负载不均)。hash $cookie_JSESSIONID
:基于SessionID绑定服务器,解决Session一致性问题。
Memcached与Session共享
Memcached:基于Key-Value的内存缓存系统,支持序列化数据存储,无持久化功能,依赖集群同步保证数据一致性,适合存储Session。
Session共享方案:通过memcached-session-manager(MSM)
实现Tomcat Session备份,将Session存储于Memcached集群,避免单机故障丢失会话。
技术运用场景
架构选型
- 小型应用:选择单体架构(Tomcat单机部署),降低开发运维成本。
- 大型应用:采用微服务架构,结合Spring Cloud/Dubbo拆分服务,通过Nginx+Tomcat集群实现负载均衡。
性能优化
- 静态资源由Nginx处理,动态请求代理至Tomcat,减少Tomcat压力。
- 启用Memcached缓存热点数据(如用户Session),提升响应速度。
高可用设计
- 多Tomcat实例部署,通过Nginx负载均衡避免单点故障。
- 基于MSM+Memcached实现Session跨节点共享,保证服务中断后会话不丢失。
实验原理
Tomcat 工作原理
Tomcat 是一个 Servlet/JSP 容器,负责处理动态网页请求。当用户发送 HTTP 请求时,Tomcat 的 Catalina 组件(Servlet 容器)会解析请求并调用对应的 Servlet 处理业务逻辑。如果是 JSP 页面,Jasper 引擎会先将 JSP 编译成 Servlet 代码再执行,最终生成 HTML 返回给用户。
Nginx 反向代理原理
Nginx 作为反向代理,通过 proxy_pass
指令将动态请求(如 .jsp
)转发给后端的 Tomcat 服务器。用户直接与 Nginx 交互,看不到真实的 Tomcat 服务器地址,既提升了安全性,又简化了客户端访问。
Nginx 负载均衡原理
Nginx 通过 upstream
配置定义多个后端服务器(如多个 Tomcat 实例),根据预设策略(如轮询、IP 哈希)分配请求。这样可以避免单台服务器过载,提高系统整体吞吐量和稳定性。
Memcached 实现 Session 共享
多台 Tomcat 共享 Session 时,借助 MSM(Memcached Session Manager)工具监控 Session 变化,实时将 Session 数据序列化存储到 Memcached 集群。如果某台 Tomcat 宕机,新请求会被路由到其他 Tomcat 节点,并从 Memcached 读取之前的 Session 数据,确保会话不中断。
实验步骤
SSH 免密登录配置
通过ssh-keygen -t rsa生成 RSA 密钥对,再使用ssh-copy-id将公钥分发到目标主机,实现多主机间免密码登录,为后续集群操作简化身份验证流程。
ssh-copy-id -i ~/.ssh/id_rsa.pub user@host 部署公钥
ssh-keygen -t rsa 生成密钥对
实验1:Tomcat安装与启动
先安装 Java 1.8 环境,解压 Tomcat 压缩包并迁移至/usr/local/tomcat目录,创建tomcat系统用户并配置权限。通过编写systemd服务文件(tomcat.service),实现 Tomcat 服务的标准化启停、开机自启及状态管理,解决手动启停的繁琐问题。
安装Java环境
克隆三台主机:,nginx(web服务器),tomcatA,tomcatB(web应用服务器)
下载java1.8版本,查看java版本,查看环境目录
yum install java-1.8.0-openjdk.x86_64 -y
java -version
安装Tomcat
解压并重命名,生成程序目录
tar zxf apache-tomcat-9.0.107.tar.gz -C /usr/local/
mv /usr/local/apache-tomcat-9.0.107 /usr/local/tomcat
启动Tomcat
cd /usr/local/tomcat/bin
./startup.sh
netstat -antlupe | grep java
关闭防火墙
访问测试:浏览器输入http://192.168.1.10:8080
,显示Tomcat默认页面即成功。
另一台tomcatB同理
生成tomcat的启动文件
注意:两台tomcat都要做:
[Unit]
Description=Tomcat
#After=syslog.target network.target remote-fs.target nss-lookup.target
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,不然启动不了
进入指定目录启动
修改权限,启动成功
是8080端口
systemctl enable --now tomcat
启用自启动
netstat -tuln | grep 8080
验证端口监听
实验2:Nginx反向代理Tomcat
在 Nginx 服务器安装 Nginx 并创建虚拟主机配置,通过proxy_pass指令将.jsp动态请求转发至单台 Tomcat,实现反向代理基础功能。扩展至多 Tomcat 节点时,配置upstream模块定义集群,使用hash $cookie_JSESSIONID策略实现会话绑定,让同一用户请求稳定分发至同一 Tomcat 节点。
反向代理单机
把写好的test.jsp文件放进来
家目录是不能直接访问的
放入默认发布目录里面
这里放进来后名字有点问题
所以我重命名了一下
nginx服务器下载nginx
编辑配置文件然后启动
server {listen 80;server_name lee.timinglee.org;location ~ \.jsp$ {proxy_pass http://192.168.1.10:8080;}
}
nginx -t
检查配置语法
upstream backend { server 192.168.1.10:8080; }
定义集群节点
重启nginx -s reload
此时还不可以解析因为还没有在本机配置
换一下解析ip
去c盘
用记事本打开(管理员的身份)
以管理员的身份保存(不是另存为)
现在应该可以访问了
此时填写时的信息都会保留
页面是nginx访问的,但是这个功能是tomcat提供的
测试:浏览器访问http://lee.timinglee.org/test.jsp
,请求被转发至Tomcat处理。
如果tomcat挂了,nginx因为你的请求去连接后端服务器的时候连接不上
多机反向代理
单机的注释(上个实验),添加多机配置
upstream tomcat {server 172.25.254.10:8080;server 172.25.254.20:8080;
}
server {listen 80;server_name lee.timinglee.org;location ~ \.jsp$ {proxy_pass http://tomcat;}
}
此时还没有做会话保留,访问提交时,会直接把前面的覆盖
那么我们就要写一个会话保留
- 加上ip_hash
但是问题来了,当你同时用两个浏览器访问该页面时,出来的都是10,那这不太应该了,应该一个访问10,一个20
- 给tomcat做一个hash,当配置不同时访问的也不一样
重启nginx
关闭浏览器重新打开
只要ID(mac)一样,访问的都是同一个主机
测试:访问http://lee.timinglee.org/test.jsp
,多次刷新请求稳定分发至同一Tomcat。
浏览器也有缓存,如果发现浏览器刷不出来你想要的,就关掉重新打开,或者换一个浏览器
有一个问题,访问页面后输入数据
当用户提交数据时,后端的某台tomcat挂了,后端就立即调度到了另一台tomcat,当用户提交时,发现前面的数据全没了,IP从20跳到了10,但是数据没有了,怎么办?
解决方法:
把数据写入memcache,实现数据同步共享
实验4:Memcached安装与Session共享
实现思路
数据暂存:用户输入的数据先临时存储在 Memcached 中
状态标识:用唯一 ID(如用户 ID + 操作标识)作为 Key
全局共享:所有 Tomcat 节点通过相同的 Memcached 配置访问数据
最终落地:用户确认提交后,再将数据持久化到数据库
安装Memcached
1. 配置 Memcached 环境
安装 Memcached 服务器并启动(建议部署多节点 Memcached 集群)
两台都下memcache并改端口
yum install memcached -y
vim /etc/sysconfig/memcached
systemctl enable --now memcached
默认监听的11211,但是现在只监听一个端口不行了,因为有一个服务挂了,所以我们要改为监听所有端口
修改监听端口
——>
可以看到进程号和IP都改变了
tomcatA:
键值:
可以看到memcache是以键值对的方式存储的
这里是手动输入配合缓存查看实验效果
tomcatB同理
开启服务,改端口
2.添加依赖
在所有 Tomcat 服务器上添加 Memcached 客户端依赖(如spymemcached)
配置Tomcat Session共享
- 下载MSM相关JAR包(如
memcached-session-manager-tc9.jar
、spymemcached.jar
),放入/usr/local/tomcat/lib/
。 - 修改
context.xml
配置Session共享策略。
使用 unzip jar.zip 命令进行解压
把依赖放入/usr/local/tomcat/lib/库里面
给tomcatB拷贝过去
ID改变说明重启成功
3.配置Session共享策略
tomcatA
重启,查看id有没有改变
tomcatB同理
验证:通过浏览器访问应用,检查Memcached中是否存储Session数据。
先看正常状态:提交后数据都会保存
其中一台停止服务
访问提交,IP改变,数据还在,就是实验成功
总结实验逻辑流程
环境初始化
SSH免密打通集群节点,统一安装Java和Tomcat基础环境。systemd
托管服务确保进程稳定性。
负载均衡搭建
Nginx配置proxy_pass
转发规则,静态资源本地响应,动态请求按Session哈希分发至Tomcat集群。
会话一致性保障
Memcached集群存储序列化Session,任意Tomcat节点故障时,请求自动迁移至其他节点并从缓存恢复会话数据。
验证与测试
通过停止单节点Tomcat观察请求自动切换,使用telnet
检查Memcached会话存储状态,确保故障转移无数据丢失。