分布式Session解决方案
一、session的作用?
session是一种会话跟踪技术,用于服务器与客户端保持整个通讯的会话基本信息。数据保存在服务器中,安全性比cookie稍微高一点,存储的数据量大,但是可能会占用一些服务器资源,session默认是保留30分钟的。
- 客户端浏览器向服务器发送一个请求,首先cookie会自动携带上次请求存储的数据(JSESSIONID)到服务器,服务器根据请求参数中的JSESSIONID到服务器中的session库中查询是否存在此JSESSIONID的信息,如果存在,那么服务器就知道此用户是谁,如果不存在,就会创建一个JSESSIONID,并在本次请求结束后将JSESSIONID返回给客户端,同时将此JSESSIONID在客户端cookie中进行保存。
二、 分布式session一致性问题?
简单来说,其实就是服务器集群Session共享的问题。
客户端发送一个请求,经过负载均衡后该请求会被分配到服务器集群中的任意一台,假如用户在某个时刻已经进行了登录验证了,如果用户再发送一个请求,该请求可能会被分配到集群中另一服务器上(并不是之前第一次请求的那一台服务器),此时检查cookie中的sessionId发现服务器没有,这时候就会出现用户重新需要登录的现象,这就是分布式环境下session不一致导致的问题。
三、分布式session解决方案
【a】cookie客户端存储
此种方式主要是利用另外一种会话跟踪技术-cookie直接保存在客户端的浏览器中。cookie保存的数据量不能很大,安全性也比session差,所以此种方式在实际应用中不常见。
优点:
- 获取方便,直接使用cookie的相关API就可以进行保存
缺点:
- 数据存储在客户端,可能会泄露信息,安全性不高;
- cookie能够存储的数据量有限;
【b】session复制
session复制是小型企业应用使用比较多的一种服务器集群session管理机制。
应用服务器开启web容器的session复制功能,在集群中的几台服务器之间同步session对象,使每一台服务器都保存了所有用户的session信息,这样任意一台服务器发生宕机也不会出现session丢失的情况,而服务器使用session时,也只需在本机获取即可。
优点:
- 配置相对比较简单,只需要简单的配置就能实现session复制功能;
- 集群中任意一台服务器的session都是一致的,这样集群中任意一台服务器发生宕机也不会出现session丢失的情况;
缺点:
- session同步的原理是在同一个局域网里面通过发送广播来异步同步session的,如果服务器多了,session需要同步大量的数据,可能会造成一定的网络开销;
【c】session绑定
session绑定主要是通过nginx反向代理服务器来配合完成,其实就是我们可以基于nginx的ip-hash策略,对客户端和服务器进行绑定,同一个客户端就只能访问该服务器,无论客户端发送多少次请求都被同一个服务器处理。
nginx.conf配置如下:
upstream tomcat_pool{
Ip_hash;
server 192.168.35.106:8080;
Server 192.168.35.106:8081;
}
server {
listen 80;
server_name www.weixiaohuai.cn;
#root /usr/local/nginx/html;
#index index.html index.htm;
location / {
proxy_pass http://tomcat_pool;
index index.html index.htm;
}
}
优点:
- 通过简单的nginx配置就完成,简单方便;
缺点:
- 容易造成单点故障,如果有一台服务器宕机,那么该台服务器上的session信息将会丢失;
- 配置了IP绑定就不支持Nginx的负载均衡;
【d】基于redis存储session方案(推荐使用)
Spring提供了一个解决方案:Spring-Session用来解决两个服务之间Session共享的问题。
流程示意图:
实现原理:
当Web服务器接收到请求后,请求会进入对应的Filter进行过滤,将原本需要由Web服务器创建会话的过程转交给Spring-Session进行创建。Spring-Session会将原本应该保存在Web服务器内存的Session存放到Redis中,然后Web服务器之间通过连接Redis来共享数据,达到Sesson共享的目的。
优点:
- 目前企业使用最多的一种方式,采用第三方存储session的方式;
- redis可进行集群环境搭建,搭建主从复制,提高session安全性、可靠性;
- spring为我们封装好了spring-session,直接引入spring-session-data-redis、spring-boot-data-starter-redis依赖即可,然后配合@EnableRedisHttpSession注解开启spring session管理功能;
缺点:
- 多了web容器需要向redis访问的一次请求,但是比起优点,可以忽略不计。
四、总结
以上说的四种方案都可以使用,相对来说使用redis等第三方存储的方案较常见,几个方案各有优劣,需要在具体的场景中做出选择和权衡。