avatar

Session一致性问题

问题描述

出现这个问题的原因,从根本上来说是因为Http是一个无状态的协议。客户端和服务端在某次会话中产生的数据不会被保留下来,所以第二次请求服务端无法认识到你曾经来过,Http为什么要设计成无状态协议呢?早起都是静态页面无所谓有无状态,后来有动态的内容更丰富,就需要有状态,出现两种用于保持Http状态的技术,那就是Cookie和Session。下图是一个简单的登录场景,因为无法正确的获取到登录用户的session,所以一直处于不停的登录状态。

解决办法

出现这种问题的原因就是因为服务端多个服务之间session不一致导致的,服务无法找到正确的session所以会出现很多莫名其妙的问题

Nginx的IP_HASH负载均衡(推荐)

Nginx的IP_HASH策略(可以用)
同一个客户端ip的请求都会被路由到同一个目标服务器,也叫作会话粘滞
优点:

  • 配置简单,不入侵应用,不需要额外修改代码
    缺点:
  • 服务器重启Session丢失
  • 存在单点负载高的风险
  • 单点故障问题

Session复制(不推荐)

多个tomcat之间通过修改配置文件,达到Session之间的复制

优点:

  • 不入侵应用
  • 便于服务器水平扩展
  • 能适应各种负载均衡策略
  • 服务器重启或者宕机不会造成Session丢失
    缺点:
  • 性能低
  • 内存消耗
  • 不能存储太多数据,否则数据越多越影响性能
  • 延迟性

Session共享,Session集中存储(推荐)

Session的本质就是缓存,那么不如将Session数据交给缓存中间件处理,例如redis

优点:

  • 能适应各种负载均衡策略
  • 服务器重启或者宕机不会造成Sessin丢失
  • 扩展能力强
  • 适合打击群数量使用
    缺点:
  • 对应用程序有入侵,引入了和Redis的交互代码
使用Spring Session操作Session
  • 引入jar包
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
    </dependency>
  • 配置redis
    spring.redis.database=0
    spring.redis.host=127.0.0.1
    spring.redis.port=6379
  • Spring启动类添加注解EnableRedisHttpSession
    // 启动Spring Session
    @EnableRedisHttpSession
    public class LoginApplication {
    public static void main(String[] args) {
    SpringApplication.run(LoginApplication.class, args);
    }
    }
Spring Session原理说明

Spring-Session通过在过滤器中进行对request封装,将内部的session通过redis进行操作

文章作者: zenshin
文章链接: https://zlh.giserhub.com/2022/01/15/cl35o0mr80041p4tg112887j5/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 zenshin's blog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论