springboot 的共享session方案?
问:springboot 的共享session方案?
参考:
- https://juejin.cn/post/7195227930077691963
- 分布式之session共享问题 4种解决方案及spring session的使用_分布式session共享方案-CSDN博客
什么是 Session ?
答:因为Http协议是无状态的,而客户端与服务器之间的交互过程可以看成是一次会话,当会话结束后,服务器并不能记录会话的状态。所以服务器采用了一种技术去记录服务器和客户端会话状态,这种技术就是Session。
补充:
Cookie是通过服务器通知客户端在客户端中保存一小块数据(键值对)的一种技术。所以Cookie是存储在客户端中的,并且客户端有了Cookie后每次请求服务器都会携带上Cookie的数据,每个Cookie的大小不能超过4kb。
Session的创建及获取流程:因为Session是基于Cookie实现的,接下来再看看Session的创建及获取过程。
分布式下Session的共享问题及解决方案
如果是集群服务下,客户端多次请求时可能请求的服务器不同,导致获取不到客户端之前的Session对象。这就是Session共享问题。
解决方案主要分为3种:
- Session复制(同步)
- 一致性hash(粘性session绑定)
- 客户端存储
- 统一存储(通过DB或缓存存储session)
Session 复制
两种实现方式:
- Tomcat服务器支持修改配置来实现Session共享
- 采用广播方式,当一台服务器的session发生改变时,将session的信息序列化后通过广播的方式通知其他服务器以此来实现Session共享
缺点:
- session同步需要数据传输,会占用大量带宽,降低服务器集群的业务处理能力。一般不采用这种的方式。
客户端存储
用户的信息不再保存在服务器中,而是保存在客户端(浏览器)中。
优点:服务器不需要保存用户信息,节省服务器资源
缺点:一般不使用这种方式
- 每次http请求,携带用户在cookie中的完整信息,浪费网络带宽
- 用户信息存储在cookie中,存在泄漏、篡改、窃取等安全隐患
- 用户信息存放在cookie中,cookie有长度4k限制,不能存放大量信息
一致性hash(粘性session绑定)
通过一致性哈希的方式实现负载均衡算法,使得客户端每次访问服务器时每次都能访问相同的服务器。(nginx的负载均衡算法里有ip_hash机制,可以将某个ip下的所有请求都定向到一台服务器之间,实现用户与服务器之间绑定)
优点:操作简单,不需要去对session进行任何操作。
缺点:当某台服务器宕机或者需要水平拓展服务器时,rehash后会导致部分session重新分布,会存在部分用户获取不到正确的Session。
统一存储(通过DB或缓存存储session)
实现方式:
- 将session存储到数据库中,所有服务器均可访问,使得session持久化。
- 将session存储到**缓存(redis)**中,所有服务器均可访问。
优点:可以支持水平拓展服务器,服务器重启也不会导致session丢失,没有安全隐患。
缺点:增加了一次网络调用(多了一次 服务器需要向 Redis 服务器发起一次网络调用来获取session数据),导致获取session速度变慢,并且访问缓存还是数据库中的数据肯定没有直接访问服务器本地的内存快。如果放在数据库中,当session使用量过大时,可能会导致数据库压力过大。
Spring Session的使用
这里详细介绍使用第三种解决方案,**使用Spring Session结合Redis的方式实现session共享。**Spring Session 是 Spring 的一个子项目,通过把servlet容器实现的httpSession
替换为自己封装好的springSession
,内部实现将session存储在指定的缓存服务器(redis)上。
实现原理:Spring Session其实是通过 SessionRepositoryFilter
过滤器实现将httpSession替换成自己的springSession的。