核心方案是将Session统一存入Redis实现集群共享,Apache仅作反向代理不参与Session管理,后端Java应用通过Spring Session或Shiro+Redis自定义DAO对接Redis,需保障Redis高可用、Cookie透传、序列化一致及超时同步。

核心思路是把 Session 数据从各节点本地内存中抽离出来,统一存到 Redis 中,让所有应用节点都读写同一份数据。Apache 在这里通常指 Apache HTTP Server(前端反向代理),它本身不管理 Session,真正需要改造的是后端 Java 应用(如 Spring Boot 或 Shiro)的会话机制。
明确角色分工
Apache 作为反向代理或负载均衡器,只负责将请求分发到后端多个 Tomcat 或 Jetty 实例;Session 一致性不靠 Apache 实现,而是由后端应用框架 + Redis 共同完成:
- Apache 不存储、不修改、不感知 Session 内容,仅转发带 Cookie: JSESSIONID=xxx 的请求
- 后端 Java 应用需替换默认的内存 Session 管理器,改用基于 Redis 的实现(如 Spring Session 或 Shiro + RedisSessionDao)
- Redis 作为中心化存储,所有节点通过相同连接参数访问同一实例(或高可用集群)
Spring Session 方案(推荐,侵入小、配置简洁)
适用于 Spring Boot 或传统 Spring MVC 项目,无需修改业务代码,只需引入依赖并启用配置:
- 添加 Maven 依赖:
spring-session-data-redis、spring-boot-starter-data-redis、jedis或lettuce - 在配置类上加
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) - application.yml 中配置 Redis 连接信息(host/port/password/database)
- 启动后,所有
HttpSession操作自动读写 Redis,JSESSIONID 仍由容器生成并透传,Apache 完全无感
Apache Shiro + Redis 自定义方案(适合已有 Shiro 架构)
当项目已深度集成 Shiro,且需精细控制 Session 生命周期时,可自定义 SessionDAO:
- 继承
AbstractSessionDAO,重写create、readSession、update、delete方法 - 使用 Jedis 或 Lettuce 将 Session 对象序列化(建议用
Kryo或Protobuf替代 Java 原生序列化)后存入 Redis,key 为 sessionId,过期时间与 session.maxInactiveInterval 对齐 - 在
applicationContext-shiro.xml中配置自定义sessionManager并注入该 DAO - 确保所有节点使用相同的 Redis 地址和序列化策略,避免反序列化失败
关键注意事项
无论选哪种方案,以下几点直接影响一致性效果:
- Redis 高可用:生产环境必须部署 Redis 主从+哨兵,或 Redis Cluster,避免单点故障导致全站登出
-
Session ID 传递无损:Apache 配置中需确保不修改、不丢弃 Cookie(尤其注意
ProxyPassReverseCookiePath和ProxyPassReverseCookieDomain) - 序列化兼容性:所有节点使用相同 JDK 版本和序列化工具;若升级应用,避免 Session 中存不可序列化对象或含私有字段变更的类
-
超时同步:Redis 的 key 过期时间必须严格等于 Session 的
maxInactiveInterval,否则会出现“Redis 已删但应用还认为有效”的状态错乱


















