1792 字
约 5 分钟
1
Session 共享入门

Session 共享入门

1. 一句话简介

在传统 Servlet 容器中,HTTP Session 保存在单台 JVM 内存里,会带来"多实例不共享、重启即失效"两个痛点。Spring Session 通过引入 spring-session-data-redis,自动注册一个 SessionRepositoryFilter,在请求入口把 Servlet 容器原生 HttpSession 透明替换为基于 Redis 的实现,业务代码里的 session.setAttribute() / session.getAttribute() 无需任何修改即可读写 Redis。本模块演示了完整的经典效果:多实例部署时所有节点共享同一登录态,应用重启后 Session 依然存在、用户不用重新登录。

2. 什么时候使用

  • 多实例部署,需要登录态共享:负载均衡下请求会落到不同实例,若 Session 各自存于 JVM 内存,用户在 A 实例登录后又被分到 B 实例就会掉线。把 Session 存进 Redis,所有实例共享同一份登录态,彻底解决共享问题。
  • 需要应用发布重启不丢登录态:每次发版重启会清空 JVM 内的 Session,导致所有在线用户强制下线。Session 存于外部 Redis 后,重启不影响登录状态,本模块的验证步骤正是"重启程序后刷新首页仍显示 token、不跳登录页"。
  • 对侵入性要求低、希望零改造:Spring Session 只替换底层 Session 实现,HttpServletRequest.getSession() 的调用方式、Session 的存值取值 API 完全不变,仅在 pom 增加依赖与几行配置即可接入。
  • 已有 Redis 基础设施、希望一技术多用:Spring Session 支持 Redis、JDBC、Hazelcast、MongoDB 等后端,若体系内已部署 Redis,直接选用 spring-session-data-redis,既能做缓存又能存 Session,无需新增中间件。
  • 单机单实例的小应用:只有一个节点且很少重启,引入 Redis 与 Spring Session 属于过度设计,原生内存 Session 更简单。
  • 对极端性能极敏感的场景:Session 读写从 JVM 内存改为走网络访问 Redis,单次多一次网络往返;且 flush-mode: immediate(逐次实时写入)与 on_save(请求结束批量写入)之间需要在实时性与写频率上做权衡。
  • 强安全缓存/敏感数据:Session 往往明文序列化存入 Redis,Redis 若未做网络隔离与加密,存在被窃取登录态的风险,需谨慎处理安全加固。
  • 访问量极大的纯会话状态系统:所有 Session 都压到单一 Redis 上会成为性能与单点瓶颈,虽可扩展,但对容量规划、Redis 高可用提出了明确的运维要求。

3. 常见业务场景

登录态共享:用户在任意后端节点完成登录后,把登录 token(本模块用 IdUtil.fastUUID() 生成的 UUID)写入 Session,所有实例都能读到同一份登录数据,实现"一次登录、集群通用"。本模块 doLogin 方法向 Session 写入 token,随后任意访问都命中已登录状态,正是这一场景的最小落地。

应用发版无感重启:系统发布新版本必然重启应用,原生 Session 会全部丢失。把 Session 放 Redis 后,重启期间浏览器 Cookie 与 Redis 中的会话数据都保持不变,用户刷新即可继续使用,无需重新登录。本模块的核心验证就是"重启程序后 Session 不失效"。

登录拦截与访问控制:借助 HandlerInterceptorAdapter 在请求进入 Controller 前检查 Session 中是否有登录凭证,无凭证则重定向到登录页。本模块的 SessionInterceptor 即校验 Session 中是否存在 SESSION_KEY 对应的 token,未登录统一 sendRedirect/page/login?redirect=true,配合 WebMvcConfigurer 的路径排除实现"默认全拦截、登录页放行"的白名单策略。

多应用 Session 隔离(命名空间化):当多个应用共用同一套 Redis 时,通过 spring.session.redis.namespace 给不同应用的 Session 加不同前缀(本模块为 spring:session),避免不同系统覆盖彼此的会话数据,实现逻辑隔离下的共享基础设施复用。

多级缓存/无状态化改造辅助:将状态的载体从 JVM 迁移到 Redis 后,应用实例本身变"无状态",可水平随意伸缩、滚动更新,横向扩展不再受 Session 粘滞绑定限制,为实现真正的弹性扩缩容奠定基础。

4. 同类技术对比

维度 Spring Session + Redis 原生 Servlet HttpSession Session 粘滞(Sticky Session) JWT 无状态 Token
Session 存储 外部 Redis,独立于应用 JVM 内存 JVM 内存(各实例各自存) 客户端,服务端无状态
多实例共享 天然支持,所有实例共享同一 Redis 不支持 依赖负载均衡把同一用户固定到同一节点 天然支持,任何节点可验证
应用重启 不丢失,Redis 中数据保留 全部丢失,需重新登录 重启该节点即丢失 不丢失
登录失效控制 服务端可主动销毁/过期 依赖容器管理 依赖容器管理 需依赖黑名单/短 TTL,较难主动撤销
无状态性 中等,实例仍依赖 Redis,但可无状态化 有状态 有状态 完全无状态,可任意扩缩容
数据安全 明文落入 Redis,需安全加固 在 JVM 内部,不外露 在 JVM 内部 Token 需防被篡改/破解,密钥需妥善保管
侵入性与成本 低侵入,pom 加依赖 + 几行配置 零配置 依赖网关/负载均衡配置 需改认证与请求解析逻辑,侵入较高
适用规模 多实例中型 Web 应用 单机小应用 中小型但需保证粘滞的集群 微服务、前后端分离、跨域跨服务

选型建议:多实例部署且希望登录态共享、发版不重启掉线的传统 Web 应用,首选 Spring Session + Redis,它在侵入性、无状态化与实现成本之间最均衡,是分布式 Session 的事实标准;单机小应用直接用原生 HttpSession,避免引入中间件;已有网关注入能力、分片压力主要在单点 Redis 上且能接受节点内失忆的旧系统,可退而求其次用 Sticky Session;面向微服务、前后端分离、需要跨服务无状态认证与水平无限扩缩容的新架构,则优先 JWT 这类无状态 Token,付出的代价是登录态主动撤销较难。需要说明的是,JWT 是"认证载体"、Spring Session 是"会话存储",二者并非完全同类,选择时还应结合已有的认证体系(如 Spring Security)一并考量。

Session 共享入门
http://clxhxhhr.top/posts/502/
作者
clxstart
发布于
2026-09-07
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。