文章目录
-
- [1.1 核心概念](#1.1 核心概念)
- [1.2 静、动态网页](#1.2 静、动态网页)
- [1.3 同步、异步](#1.3 同步、异步)
- [2 Web架构](#2 Web架构)
-
- [2.1 单体架构(Monolithic)](#2.1 单体架构(Monolithic))
- [2.2 微服务架构(Microservices)](#2.2 微服务架构(Microservices))
- [2.3 常见Web服务器/容器](#2.3 常见Web服务器/容器)
- [3 Tomcat](#3 Tomcat)
-
- [3.1 定位](#3.1 定位)
- [3.2 核心功能](#3.2 核心功能)
- [3.3 核心组件](#3.3 核心组件)
- [3.4 目录结构](#3.4 目录结构)
- [4 反向代理与负载均衡](#4 反向代理与负载均衡)
-
- [4.1 部署方式演进](#4.1 部署方式演进)
- [4.2 LNMT/LAMT架构对比](#4.2 LNMT/LAMT架构对比)
- [4.3 Session问题详解](#4.3 Session问题详解)
- [5 Memcached缓存](#5 Memcached缓存)
-
- [5.1 简介](#5.1 简介)
- [5.2 与Redis对比](#5.2 与Redis对比)
- [5.3 基本命令详解](#5.3 基本命令详解)
- [6 Session共享方案(MSM)](#6 Session共享方案(MSM))
-
- [6.1 背景](#6.1 背景)
- [6.2 所需Jar包](#6.2 所需Jar包)
- [6.3 工作原理](#6.3 工作原理)
-
1. Web技术
1.1 核心概念
| 概念 |
说明 |
| B/S架构 |
Browser/Server,浏览器/服务器模式。客户端只需浏览器,业务逻辑集中在服务器,维护成本低,但受网络影响大 |
| C/S架构 |
Client/Server,客户端/服务器模式(如QQ、迅雷、游戏客户端)。需安装专用软件,性能好、功能强,但升级维护麻烦 |
| HTTP协议 |
HyperText Transfer Protocol,应用层文本传输协议,1990年由Tim Berners-Lee发明,默认端口80,HTTPS为443 |
| 动态网页 |
服务端根据请求动态生成HTML。演进:CGI(通用网关接口)→ ASP/PHP/JSP(脚本嵌入HTML)→ 现代MVC框架 |
1.2 静、动态网页
| 特性 |
静态网页 |
动态网页 |
| 内容生成 |
预存HTML文件 |
服务器实时生成 |
| 交互性 |
无 |
支持用户交互、数据库操作 |
| 扩展名 |
.html/.htm |
.php/.jsp/.asp/.py等 |
| 性能 |
加载快,适合CDN |
需服务器处理,相对较慢 |
| 适用场景 |
企业官网、文档 |
电商、社交、管理系统 |
1.3 同步、异步
| 方式 |
特点 |
技术实现 |
| 同步 |
请求后整个页面刷新,用户体验差,服务器压力大 |
传统form提交、超链接跳转 |
| 异步(Ajax) |
局部更新,不刷新整个页面,提升用户体验和性能 |
XMLHttpRequest、Fetch API、Axios |
Ajax工作流程:JavaScript发起异步请求 → 服务器返回数据(JSON/XML)→ JavaScript更新DOM局部内容
2 Web架构
2.1 单体架构(Monolithic)
- 定义:所有功能模块打包在一个应用中,统一部署运行
- 优点 :
- 易于开发测试:单一代码库,调试方便
- 部署简单:一个WAR/JAR包直接部署
- 扩展方便:水平复制(多实例部署)
- 事务处理简单:本地事务即可保证一致性
- 缺点 :
- 耦合度高:模块间边界模糊,代码纠缠
- 全站风险:任一模块故障影响整个系统
- 技术栈锁定:难以引入新技术
- 不适合快速迭代:小改动需全量部署
- 团队协作难:大量开发者冲突频繁
2.2 微服务架构(Microservices)
- 核心思想:按业务领域拆分成独立服务,一个服务只做一件事(单一职责原则)
- 服务特征 :
- 独立部署、独立扩展
- 拥有自己的数据库(Database per Service)
- 轻量级通信机制
- 通信方式:HTTP RESTful API、消息队列(RabbitMQ/Kafka)、gRPC
- 基础设施:服务注册发现(Eureka/Nacos)、配置中心、网关(Gateway)、熔断限流(Hystrix/Sentinel)
- 优点 :
- 松耦合:服务间通过接口通信
- 独立部署:单个服务升级不影响全局
- 小团队开发:2 Pizza Team(亚马逊原则)
- 技术栈灵活:不同服务可用不同语言/框架
- 故障隔离:单点故障不会拖垮整体
- 缺点 :
- 分布式复杂性:网络延迟、超时、重试
- 数据一致性挑战:分布式事务(Saga、TCC模式)
- 运维成本高:监控、日志、链路追踪
- 测试复杂:集成测试需协调多服务
2.3 常见Web服务器/容器
| 类型 |
产品 |
特点 |
| 开源 |
Tomcat |
Apache开源,Servlet/JSP容器,轻量 |
|
Jetty |
Eclipse开源,嵌入式场景,轻量快速 |
|
GlassFish |
Oracle开源,Java EE完整实现 |
|
Undertow |
JBoss开源,基于NIO,性能高 |
| 商用 |
WebLogic |
Oracle,企业级,功能全面,收费 |
|
WebSphere |
IBM,大型金融电信首选,收费 |
|
JBoss EAP |
RedHat,开源+商业支持 |
3 Tomcat
3.1 定位
- 官方定义 :Apache Tomcat是开源的Servlet容器(Servlet Container),实现了Java EE(现Jakarta EE)中的Servlet、JSP、WebSocket等规范
- 与Web服务器区别 :
- Web服务器(如Nginx、Apache Httpd):处理静态资源、反向代理、负载均衡
- Servlet容器(如Tomcat):运行Java Web应用,处理动态请求
- 双重角色:既是Servlet容器,也可作为轻量级Web服务器使用(支持静态资源,但性能不如Nginx)
3.2 核心功能
| 功能 |
说明 |
| Servlet生命周期管理 |
加载、初始化、调用service()、销毁Servlet实例 |
| 请求处理 |
监听端口(默认8080),解析HTTP请求,分发给对应Servlet |
| JSP编译执行 |
将JSP翻译为Servlet源码,编译为class并执行 |
| 会话管理 |
Session创建、维护、持久化(支持Cookie/URL重写) |
| 连接器架构 |
Coyote(HTTP连接器)+ Catalina(Servlet容器) |
| 多协议支持 |
HTTP/1.1、AJP(Apache JServ Protocol,与Apache Httpd集成) |
3.3 核心组件
- Catalina:Servlet容器核心,实现Servlet规范
- Coyote:HTTP连接器,处理网络连接、解析HTTP协议
- Jasper:JSP引擎,负责JSP编译
- Cluster:集群组件,支持Session复制
- Realm:安全域,提供用户认证授权
3.4 目录结构
bash
复制代码
$CATALINA_HOME/
├── bin/ # 启动/关闭脚本(startup.sh/shutdown.sh)
├── conf/ # 配置文件(server.xml、web.xml)
├── lib/ # 公共类库(Servlet API、JDBC驱动等)
├── logs/ # 日志文件
├── webapps/ # 部署目录(WAR包自动解压)
├── work/ # JSP编译后的Servlet源码和class
└── temp/ # 临时文件
4 反向代理与负载均衡
4.1 部署方式演进
| 模式 |
架构 |
适用场景 |
说明 |
| Standalone |
Tomcat单独运行 |
开发测试环境 |
直接暴露Tomcat,性能差、不安全,生产不推荐 |
| 单机反向代理 |
Nginx→Tomcat |
中小型应用 |
Nginx处理静态资源(CSS/JS/图片),动态请求转发Tomcat,动静分离 |
| 反向代理多机 |
Nginx→多Tomcat |
高并发生产环境 |
负载均衡(轮询/权重/IP哈希),Tomcat水平扩展 |
| 多级代理 |
Nginx→Nginx→Tomcat |
超大规模/多机房 |
LVS/Nginx做四层负载,Nginx做七层负载,Tomcat集群 |
4.2 LNMT/LAMT架构对比
| 架构 |
组件 |
特点 |
| LNMT |
Linux + Nginx + MySQL + Tomcat |
性能高、并发强、配置简洁、资源占用低,现代主流选择 |
| LAMT |
Linux + Apache(Httpd) + MySQL + Tomcat |
Apache模块丰富、.htaccess灵活、与PHP集成好,传统LAMP变种 |
Nginx vs Apache Httpd:
- Nginx:异步非阻塞事件驱动,高并发低内存,适合反向代理
- Apache:进程/线程模型,模块多、功能全,适合复杂业务逻辑
4.3 Session问题详解
- HTTP无状态本质:每个请求独立,服务器不保存客户端上下文
- Session机制 :
- 首次请求:服务器创建Session对象,生成唯一SessionID
- 响应头:Set-Cookie: JSESSIONID=xxx
- 后续请求:浏览器自动携带Cookie,服务器通过ID找到Session
- 负载均衡下的Session问题 :
- 请求1→Tomcat A(创建Session)
- 请求2→Tomcat B(无此SessionID,重新创建→用户登录状态丢失)
- 解决方案 :
- Session复制(Tomcat Cluster):实时同步Session到所有节点,网络开销大
- Session粘滞(IP Hash):固定用户到固定节点,单点故障风险
- Session集中存储(Memcached/Redis):推荐方案,MSM实现
5 Memcached缓存
5.1 简介
- 定位:高性能分布式内存对象缓存系统,LiveJournal团队2003年开发
- 设计哲学:简单、快速、分布式,专注缓存不做持久化
- 核心特点 :
- 纯内存操作,读写速度极快(微秒级)
- 基于libevent实现高效事件驱动网络IO
- 分布式:客户端通过一致性哈希选择服务器节点
- 不支持持久化:重启数据丢失,纯缓存用途
- LRU淘汰:内存满时自动淘汰最少使用数据
- 限制 :
- 单个对象最大1MB(适合Session、小对象,不适合大文件)
- 仅支持Key-Value(String),无复杂数据结构
- 无认证机制,需部署在内网
5.2 与Redis对比
| 特性 |
Memcached |
Redis |
| 数据结构 |
仅String |
String、Hash、List、Set、ZSet等 |
| 持久化 |
不支持 |
RDB快照、AOF日志 |
| 集群 |
客户端分片 |
Redis Cluster原生支持 |
| 功能 |
简单缓存 |
缓存、消息队列、分布式锁等 |
| 内存管理 |
预分配内存池 |
现场申请内存 |
| 适用场景 |
纯缓存、简单KV |
复杂数据结构、持久化需求 |
5.3 基本命令详解
| 命令 |
说明 |
示例 |
返回值 |
set |
设置/更新键值(存在覆盖,不存在创建) |
set username 0 3600 5 |
STORED/ERROR |
add |
仅新增(键不存在才添加) |
add counter 0 60 1 |
STORED/NOT_STORED |
replace |
仅替换(键存在才更新) |
replace config 0 0 10 |
STORED/NOT_STORED |
get |
获取值 |
get username |
VALUE...END |
gets |
获取值和CAS令牌(用于乐观锁) |
gets username |
含版本号 |
delete |
删除键 |
delete oldkey |
DELETED/NOT_FOUND |
incr/decr |
原子增减(仅数字) |
incr counter 1 |
新值/ERROR |
flush_all |
清空所有数据(危险!) |
flush_all |
OK |
stats |
查看统计信息 |
stats |
多行状态数据 |
参数格式 :command <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n
- key:键名,最大250字节,不能含空格/控制字符
- flags:16位无符号整数,存储额外标记(如数据类型),客户端自定义
- exptime :过期时间(秒)
- 0 = 永久存储(但受LRU淘汰)
- 30天内:秒数(如3600=1小时)
- Unix时间戳:1970年1月1日以来的秒数
- bytes:数据字节数(不含\r\n),必须与value实际长度一致
- noreply:可选,不等待服务器响应(提升性能)
6 Session共享方案(MSM)
6.1 背景
MSM(Memcached Session Manager):开源Tomcat扩展,将Session序列化后存储到Memcached,实现:
- Session共享:多Tomcat实例共享同一Session存储
- 高可用:Memcached集群故障时自动切换节点
- 弹性伸缩:Tomcat实例随意增减,不影响用户会话
6.2 所需Jar包
将以下jar包放入 $CATALINA_HOME/lib/ 目录:
| Jar包 |
作用 |
| memcached-session-manager |
MSM核心 |
| memcached-session-manager-tc9 |
Tomcat 9适配器(根据Tomcat版本选择tc7/tc8/tc9) |
| spymemcached |
Memcached Java客户端驱动 |
| kryo |
高性能Java序列化库(替代默认Java序列化) |
| kryo-serializers |
Kryo扩展序列化器 |
| minlog |
Kryo依赖 |
| objenesis |
Kryo依赖(无参构造实例化) |
| asm |
字节码操作库 |
版本匹配:tc9对应Tomcat 9.x,tc8对应Tomcat 8.x,务必匹配
6.3 工作原理
Sticky模式(粘性会话,推荐)
bash
复制代码
用户请求 → Nginx(IP Hash固定到Tomcat A)→ Tomcat A
↓
Session存储:Memcached Node 1(主)
↓
异步备份到:Memcached Node 2(备)
流程:
- Tomcat A创建Session,同时写入Memcached Node 1(主)
- 异步复制到Memcached Node 2(备)
- 用户后续请求始终到Tomcat A,直接从本地内存读Session(性能最优)
- 故障切换:若Tomcat A宕机,Nginx将请求转发到Tomcat B
- Tomcat B发现无本地Session,去Memcached Node 1读取,恢复用户状态
Non-Sticky模式(非粘性)
bash
复制代码
用户请求1 → Tomcat A → 写入Memcached Node 1/2(根据SessionID哈希)
用户请求2 → Tomcat B → 从Memcached读取(可能不同节点)
特点:每个请求都可能到不同Tomcat,每次需从Memcached读取Session,网络开销大,但Tomcat故障无感知
序列化过程
bash
复制代码
Tomcat Session对象
↓
Kryo序列化(二进制,高效)
↓
压缩(可选Snappy/LZ4)
↓
存储到Memcached(Key=SessionID,Value=序列化数据)
SessionID映射 :Memcached的Key = 会话ID + - + Tomcat标识(避免多Tomcat冲突)
故障恢复机制
- Memcached节点故障:自动切换到备份节点,Session不丢失(Sticky模式)
- Tomcat节点故障:Nginx剔除故障节点,请求转到其他Tomcat,从Memcached恢复Session
- 网络分区:依赖Memcached集群自身的高可用(如Repcached双向复制)