一. 分布式下session共享问题
- 同一个服务,复制多份,session不同步问题
- 不同服务,session不能共享问题(子域session,域名不同)
二. session共享问题解决 – session复制
- 优点
- web-server(Tomcat)原生支持,只需要修改配置文件
- 缺点
- session同步需要数据传输,占用了大量的网络带宽,降低了服务器群的业务处理能力
- 任意一台web-server保存的数据都是所有web-server的session总和,受到内存限制无法水平扩展更多的web-server
- 大型分布式集群情况下,由于所有web-server都全量保存数据,所以此方案不可取
三. session共享问题解决 – 客户端存储
- 优点
- 服务器无需存储session,用户保存自己的session信息到cookie中,节省服务端资源
- 缺点
- 每次http请求,都携带用户在cookie中的完整信息,浪费网路带宽
- session数据放在cookie中,cookie有长度限制4k,不能保存大量数据
- session数据放在cookie中,存在泄漏,篡改,窃取等安全隐患
- 缺点太多,只能作为一种思路
四. session共享问题解决 – hash一致性
- 优点
- 只需要修改nginx配置,不需要修改应用代码
- 负载均衡,只要hash属性的值分布是均匀的,多台web-server的负载是均衡的
- 可以支持web-server水平扩展
- 缺点
- session还是存在web-server中的,所以web-server重启可能导致部分session丢失,影响业务,如部分用户需要重新登录
- 如果web-server水平扩展,rehash后session重新分布,也会有一部分用户路由不到正确的session
五. session共享问题解决 – t统一存储
- 优点
- 没有安全隐患
- 可以水平扩展,数据库/缓存水平水平切分即可
- web-server重启或扩容都不会有session丢失
- 不足
- 增加了一次网络调用,并且需要修改应用代码,如将所有的getSession方法替换为从redis查询数据的方式,redis获取数据比内存慢很多
- 上面的缺点可以用springSession完美解决
六. 整合springSession解决session共享问题 和 子域session共享问题
-
依赖
-
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
-
-
配置
-
spring.session.store-type=redis
使用redis存储session -
server.servlet.session.timeout
session的超时时间 -
springsession.redis.flush-mode=on-save
redis刷新策略 -
spring.session.redis.namespace
session存储的前缀 -
配置redis连接信息 使用redis连接池需要引入commons-pool2包
-
主启动类添加**@EnableRedisHttpSession**
-
lettuce连接池
-
配置Bean CookieSerializer(DefaultCookieSerializer) 设置domain即可改变cookie的作用域(改为父域名)
-
配置Bean ResdisSerializer 使用其子类即可将cookie以json格式存入redis 如(GenericFastJsonRedisSerializer),采坑(bean的名字必须为springSessionDefaultRedisSerializer,即@Bean的方法名)
-
-
原理: 装饰者模式 定义一个拦截器对request和response进行包装,重写了其包装类的getSession()方法 使用SessionRepository进行获取session,而@EnableRedisHttpSession注解注入了RedisOperationsSessionRepository