想解决分布式Session共享的问题,首先我们需要先知道Session的工作原理是什么:
了解了原理之后,问自己三个问题:
1、Tomcat中的Session保存在哪?
答:存储在Tomcat本地的ConcurrentHashMap中(本地缓存),以sessionid为key。
2、Tomcat是怎么追踪到请求是属于哪个Session?
答:通过cookie产生会话时向浏览器发送存有sessionid的cookie,后续请求都带上这个cookie。
3、Session是不是在用户登录时就产生了?
答:不是,会话是用来跟踪多个请求的,登录只是明确会话是谁(把用户信息存放到session中)。
那为什么需要进行session共享呢?这就的从分布式集群部署说起了。。。
简单的集群部署的架构如下图所示:
简单说一下上面的架构,有一个关键点是反向代理,简单理解反向代理,就是为集群找个代理,接收用户请求,再分发给集群中的服务器。
而对于这个作为反向代理的中间件,最起码有如下两个要求
- 并发负载能力强
- 能均衡的分发请求
而常用的反向代理(负载均衡)中间件,常见的主要有如下两类:
硬件:NetScaler、F5、Radware和Array等。
因为价格比较高昂,但也提供了高可用性和稳定性,同时还提供专业的技术服务。专业的IT团队大企业采用。
软件:Nginx、HaProxy、LVS等。
这三种负载均衡器都是开源软件,小企业和互联网公司必选。
如果想要达到无限的并发,一般是软硬结合的方式,比如典型的组合:DNS + F5 + LVS + Nginx。但是90%的企业采用F5 + LVS + Nginx这类组合就满足高并发需求,大概可以支持到1000w的并发量。毕竟F5还是收费的,所以初创企业,在用户量没有那么大的时候,LVS + Nginx这类组合就够了,大概可以支持到50w的并发。
下面主要介绍一下非常流行的Nginx,具体详见下图:
Nginx主要支持的负载均衡策略有如下四个:
- 轮询(集群中服务器轮着被访问)
- Weight权重(适用于服务器配置不同的场景)
- IP_HASH(总是路由到固定的服务器)
- 支持扩展自定义策略
上面说了这么多,貌似还是没有说分布式部署会产生什么问题:比如集群中只有两台服务器A和B,负载均衡的策略设置的为轮训。当第一次请求的时候,比如登录某个系统,session会存储到服务器A上;当登录之后,发起另一个请求比如访问系统中某个功能,此时请求会路由到服务器B上,而此时服务器B因为之前没有被访问过,所以不存在该用户session,认证失败,还会让你再登录一次,这就产生问题了。这就是典型的Session共享或者叫做Session一致性的问题。
最后终于轮到到今天的主角了,对于上面session一致性的问题,常用解决方案主要有如下三种:
1、服务器session间进行复制(用的很少)
2、ip_hash策略
3、Session统一缓存(现在最常用)
服务器间Session复制
先说下第一个,服务器间session复制,比如用Tomcat,需要如下两个步骤:
- 修改server.xml中的Cluster节点
- 修改应用web.xml,增加节点:<distributable />
ip_hash策略
拿Nginx举例,需要修改nginx.conf,添加ip_hash策略
upstream test{ ip_hash; server 192.168.1.190:8080; server 192.168.1.190:8081; }
Session统一缓存
拿Redis举例,比如项目用Springboot,主要用spring-session-data-redis去对redis进行读写操作。
最后对三者做一个总结: