一、我们知道Session的常见形式是会话cookie,即为设置过期时间的cookie,它的默认的生命周期为浏览器会话期间,一旦浏览器关闭窗口,这个cookie就消失了。其实现机制为:当用户发起一个请求的时候,服务器会检查该请求中是否包含sessionID,如果不包含,则服务器会生成一个名为JSESSIONID的cookie返回到浏览器,(这个cookie存放在内存中,并不会存在硬盘)。同时在服务器端以HashTable的形式写到服务器内存中;当请求中包含sessionID时,服务器端会在HashTable中查找与该session相匹配的信息,若存在则直接使用该sessionID,否则重新生成新的session。
二、 Session共享:如果网站是存放在一台机器上,是不存在session共享这个问题的,因为所有的会话数据都在这一台机器上。但是,现在的网站大部分都是需要做负载均衡的,即需要把用户的请求分发到不同机器,当然这时会话ID在客户端是不存在问题的,但是服务端会出现取不到session数据的情况。如下图:
在该架构中,采用Nginx做负载均衡,两个Tomcat做后端服务器,假设当客户端第一次请求时,Nginx将其分发到了Tomcat1,这时候Tomcat1会产生sessionID返回给客户端,并同时保存在自己的内存中;当客户端第二次请求时,Nginx将其分发到了Tomcat2,这时便无法取到session。从而就会重新生成session,返回给客户端,并保存在自己的内存中。两台Tomcat中保存的同一个用户的session不同,这便是session的一致性问题。
为了解决这个问题,首当其冲,我会想到,将Tomcat1中的session复制到Tomcat2中即可,当然是可以的,但是不方便,因为这里只有两台服务器,而当后台服务器增多时,会很麻烦。从而,便有了如下的解决方法:
即,将session分离出来,每个服务器都是从该session服务器(集群)中获取。这样以来,新增加的服务器也只需从session集群中获取。
(session集群可以通过memcached或redis来实现)
三、那么我们来看看ASP.NET Core使用Redis存储Session实现分布式共享?
Session 是客户端与服务器通讯会话跟踪技术,服务器与客户端保持整个通讯的会话基本信息。客户端在第一次访问服务端的时候,服务端会响应一个sessionId并且将它存入到本地cookie中,在之后的访问会将cookie中的sessionId放入到请求头中去访问服务器,如果通过这个sessionid没有找到对应的数据那么服务器会创建一个新的sessionid并且响应给客户端。
1、为什么要分布式共享Session?
单服务器web应用中,session信息只需存在该服务器中,这是我们前几年最常接触的方式,但是近几年随着分布式系统的流行,单系统已经不能满足日益增长的百万级用户的需求,集群方式部署服务器已在很多公司运用起来,当高并发量的请求到达服务端的时候通过负载均衡的方式分发到集群中的某个服务器,这样就有可能导致同一个用户的多次请求被分发到集群的不同服务器上,就会出现取不到session数据的情况,于是session的共享就成了一个问题。这个时候就需要解决Session一致性。
2、分布式Session存在的问题?
假设第一次访问服务A生成一个sessionid并且存入cookie中,第二次却访问服务B客户端会在cookie中读取sessionid加入到请求头中,如果在服务B通过sessionid没有找到对应的数据那么它创建一个新的并且将sessionid返回给客户端,这样并不能共享我们的Session无法达到我们想要的目的。说白了一句话就是: 分布式Session存在会话不一致性的问题。
3、分布式Session解决方案有哪些?
实现分布式session的方案非常多,选型时需要一种可靠、简单的实现方式,结合我们项目中的使用经验来看,使用基于Redis实现的分布式session方案还是比较靠谱的。