Session就是存储在服务器端的用户的一些会话内容,比如:用户的登录状态、用户的一些信息、登录过期时间等等,那些经常需要获取的与当前登录用户有关的信息。
与session相对应的是cookie,cookie是浏览器存储特殊数据的一个地方,有些请求的结果会保存在cookie中,以便下次再次请求的时候,带上cookie去访问。
如果来打个比方,cookie就像是你手中的会员卡,session就像是奶茶店的管理系统中属于你的那部分信息,你每次带上自己的会员卡,一刷卡,奶茶店的软件管理系统便能取到你的一些余额信息、消费历史信息等。
一般session常用于保存登录状态、身份信息、个性配置、权限列表、其他通用数据(比如购物车等)
这些信息的一个共同点就是:每次请求中都需要获取,如果没有放在session中的话,每次都需要去查看用户的基本身份信息、用户的权限列表(用于权限判断)必然很低效且繁琐。
Session的存在就是保存:请求中经常需要使用到的信息。
如果后台应用是单体系统,那么session一般就是存储在单体应用的内存中就好,这样没有任何问题。但是如何是分布式系统,Session管理便存在问题了。
打个比方:如果因为并发等问题,一个tomcat达到瓶颈,增加了一个tomcat部署相同的单体项目,形成一个单体系统的集群模式,那么session机制有问题出现了:比如A用户第一次访问的时候,将会话信息存储到了Atomcat中,但是因为nginx将请求随机分发的缘故,第二次A用户再次请求的时候,被路由到了Btomcat,但是Btomcat中找不到之前的会话信息了。
再比如:如果把单体拆分成了微服务,用户随时可能访问到任何一个服务的任何一个实例上去,但是该用户的会话信息必须保存在一个每个实例都可以访问到的地方才行。
正是因为这些缘故,所以才有了分布式Session。
1、完全不用session:
使用JWT,其有效载荷可以存储一定量的有效信息,也就是说用户会话信息实际上放在了JWT中了。
优点是:不需要在服务器端使用专门的空间来管理session,简单。但缺点是:JWT本身可以存储的有效载荷信息有限,如果session信息过大则不合适使用JWT的方式;而且每次请求都需要拿上JWT,无形中增大了网络数据传输量。
2、Ip粘滞 / 一致性hash:
在nignx中配置即可实现,就是将同一个用户的请求全部分发到指定服务的tomcat中,保持后面的请求都可以拿到前面请求保存的会话信息。
优点是只需要简单配置以下nginx便可以实现session一致性。缺点就是如果某个tomcat宕机,必然面临大量session数据失效,以及session数据迁移等。
3、session复制:
几个tomcat中维护相同的session数据,并且相互之间进行数据复制。
缺点:频繁的数据复制,导致网络开销大
4、会话集中存储:
既然要保证每个服务的每个实例都能拿到session信息,那么session信息自然就不能存储到应用实例的内存中,而要集中存储,而且要保证每个实例都可以访问到的地方。比如可以存储到redis中,再比如可以存储到mysql中,具体的实现方式有:
①、Tomcat + redis:还是和以前一样,使用session代码,配置tomcat的RedisSessionManager,可以让我们部署的tomcat都将session数据存储到redis;
②、Spring session + redis: 将session管理权交给spring session,实际的session数据存储在redis中;
③、Shiro:支持session存储,session管理权属于Shiro框架,同时session数据源可以有多种,比如mysql,redis等等。