一口气说出 4 种分布式一致性 Session 实现方式,面试杠杠的~

前言

公司有一个 Web 管理系统,使用 Tomcat 进行部署。因为是后台管理系统,全部的网页都须要登陆受权以后才能进行相应的操做。前端

起初这个系统的用的人也很少,为了节省资源,这个系统仅仅只是单机部署。后来随着用的人愈来愈多,单机已经有点扛不住了,因而我决定再部署了一台机器。spring

这时后端系统有两台服务,因而咱们使用 Nginx 做为反向代理,总体架构图以下:后端

这个架构图想必你们应该比较熟悉,如今主流的 Web 系统应该都是这么部署。浏览器

通过一些调试以后,在一个夜深人静的晚上,将这套系统部署到了生产。本觉得没有什么事的,很稳的交给测试小姐姐开始测试。缓存

这一测,出了大问题!测试小姐姐反馈,登陆事后,没过一会又须要登陆,操做好几回都是这样。网络

检查了一下,系统应用,配置什么也没问题,那到底哪里出了问题?session

这个时候组长刚准备下班,看到咱们这里有问题,因而过来了看了一下。简单了解的一下基本状况,很快就找到了问题的缘由,而后在 Nginx 端修改了下配置,重启解决了问题。架构

先点后赞,养成习惯~关注公号『程序通事』,快来呀!!

分布式一致性 Session

解决完问题,组长坐下解释了问题缘由:分布式一致性 Session负载均衡

原先咱们登陆以后将会把用户登陆信息放在 Session 中,用户每次操做首先先校验 Session 是否存在用户信息,若是不存在将会强制让用户先去登陆。分布式

原先架构的中咱们只有一台应用系统,全部操做都在一台 Tomcat 上,这固然没有什么问题。

可是如今咱们部署了两台系统,因为 Nginx 使用默认负载均衡策略(轮询),请求将会按照时间顺序逐一分发到后端应用上。

也就是说刚开始咱们在 Tomcat1 登陆以后,用户信息放在 Tomcat1 的 Session 里。过了一会,请求又被 Nginx 分发到了 Tomcat2 上,这时 Tomcat2 上 Session 里尚未用户信息,因而又要登陆。

另外因为咱们系统采用单点登陆的方式,Tomcat2 登陆以后会将 Tomcat1 登陆信息失效,因而乎等到 Nginx 再把流量分发到 Tomcat1 时,Session 中用户登陆信息已经失效,又要从新登陆。

知道了问题,固然想知道解决办法了,因而组长教了下分布式一致性 Session 四种解决办法,小黑哥给你们整理了一下:

下面小黑哥将会以跟组长对话的形式,讲解分布式一致性 Session 解决办法。

Session 复制

组长:

若是此时 Tomcat1 Session 存在用户信息,而 Tomcat2 上没有存在。

这时若是咱们将 Tomcat1 的 Session 复制到 Tomcat2 上,后面 Nginx 将请求转发到 Tomcat2 上,因为 Tomcat2 存在 Session ,这时就不须要再从新登陆了。

架构图以下:

一致性 Session-Session 复制

Tomcat 的 Session 复制的配置,网上有比较多的例子,这里小黑就再也不贴了,感兴趣的同窗能够自行搜索一下。

小黑:

对的,这种方式挺好啊。Tomcat 就支持这种方式,咱们只须要修改 Tomcat 配置就好,咱们应用代码都不用修改了。

组长:

说的对,可是这种方式仍是有不少缺点。

第一,Session 复制传输须要占用内网带宽。

第二,咱们的例子就只有两台机器,这个复制性能还能够。可是假设咱们有 N 台机器,那么每次复制都要复制给 N-1 台机器,若是机器不少,可能会造成网络风暴,复制性能也会呈指数级降低。

第三, Tomcat 须要保存全部的 Session 数据,这个方案的 Session 存储在内存中,容易受到机器的总内存的限制。咱们没办法经过加机器的方式水平扩展,咱们能作的方式就是加大机器内存。可是机器内存越大,价格真的很贵!!!

因此不推荐使用这种方案。

Session 前端存储

小黑:

恩,这个方案确实有点不靠谱~

哎,有了!咱们的 Session 里面其实就是存了用户的信息,那我如今不存 Tomcat Session 里,我把信息拿出来,存到浏览器的 Cookie 中。

这样,每一个用户浏览器存储本身的 Cookie 信息,服务端就不须要存储,这就解决了 Session 复制方案的缺陷了。

接下来用户每次请求都把这个 Cookie 给我发过来,我判断 Cookie 里面用户信息不就行了。

架构图以下:

一致性 Session-Session 前端存储

组长,欣赏看了一下我:

对,你这个方案确实可行。

不过么,若是用这种方案,首先你要想好加密方案。

用户信息但是咱们的敏感数据,不能让别人轻易的窃取或者篡改数据了。

除了这个,这个方案每次请求都要携带 Cookie 传输,这会占用外网的带宽,若是 Cookie 过大,会增大网络的开销。

另外,咱们存储的数据大小,容易受到 Cookie 限制。

因此这种仍是不怎么经常使用,不过也是一种思路。

我比较推荐下面两种方案。

Session 粘滞(Sticky Sessions)

组长:

刚才应该看到了,我只是对 Nginx 的配置作了一些修改,而后这个问题就解决了吧。

其实这是由于我修改 Nginx 默认的负载均衡策略,使用 IP Hash 的方式。

Nginx 会使用请求者的 IP 来作 Hash,而后分发到一台机器上,这样能够保证同一 IP 的请求都落在同一台 Tomcat 上。

架构图以下:

Session 粘滞-IP Hash

上面这种方式咱们使用 Nginx 四层负载均衡方式,其实 Nginx 还能够作到七层负载均衡方式,也就是使用 Http 协议中的一些业务属性来作 Hash,常见的有 userId,loginId等等。

架构图以下:

一致性 Session-Session 粘滞-七层

小黑:

这种方案看起来挺简单的,咱们只须要修改 Nginx 配置就行了,应用端配置无需改动。

只要请求来源 IP 足够的随机,那么 IP HASH 以后两台应用上的流量将会足够随机。

另外后面若是两台机器扛不住,咱们还能够水平扩展,再加机器,只要修改 Nginx 配置便可。

组长:

你说的这几点都很正确!

不过你有没有想过,像咱们公司这种状况,全部人的出口的 IP 都是一个。那么咱们公司的全部请求只会到一台机器上,那咱们这种状况等于又变成单点了。

另外若是 Tomcat 重启,Session 因为是放置在内存内存中,这一部分的 Session 将会丢失,这就致使这部分用户将会从新登陆。

最后,若是咱们临时再加机器,修改完 Nginx 配置,从新启动以后,Nginx 将会从新计算 Hash 分发请求。

这种状况就会致使有一部分用户从新路由到一台新机器上,因为没有 Session,又须要从新登陆了。

不过么,Tomcat 重启或者新加机器次数不会不少,因此这个问题也不大,用户体验稍差点。

今天的咱们这个问题解决方案就先使用这个。

不事后面咱们仍是改为下面这种方式。

后端集中存储

组长:

上面几种的方式咱们都是把 Session 存储在应用内存上,应用机器只要重启,Session 就会丢失。

为了这个解决这个问题,咱们将 Session 单独存起来,保存到 Redis 或者 MySQL 中。

不过因为 Session 须要过时失效的特性,不须要持久化保存,因此这里我建议使用 Redis 来保存。

这样架构就变成下方这样的:

一致性 Session-Session 后端存储

咱们使用这种方案,上没有 Session 丢失的风险,固然前提是 Redis 不能宕机。

另外后期若是应用能够直接水平扩展。

若是后面应用的请求量很大,一台 Redis 扛不住了,那咱们能够其实能够作集群扩展,根据缓存 Key 作路由。

小黑:

对对,这种方式好~

组长:

你不要高兴的太早,咱们使用这个方案须要付出必定的代价的。

首先咱们每次请求都须要调用一次 Redis ,这就增长一次网络的开销。

另外,引入 Redis,咱们须要对相应的代码作出修改,这样复杂度就变高。

因此说,这个方案有利也有弊,固然对于咱们的场景来讲,利大于弊。

小黑:

恩,好像是这样的。

组长:

好了,这么晚了,问题解决了,咱们去撸个串,我请客!

小黑:

老大,🐂!

组长拍了拍小黑的脑壳:

我这一顿不是白吃哦,下个星期你把如今方式修改一下,修改为 Session 集中存储的方式。

给你一个小提示,可使用 spring-session

小黑:

好吧,吃人嘴短,下周我研究下。

总结

最后总结一下,当咱们后端 Web 应用扩展到多台后,咱们就会碰到分布式一致性 Session 的问题,主流解决方案有四种:

  • Session 复制:利用 Tomcat 等 Web 容器同步复制
  • Session 前端存储:利用用户浏览器中 Cookie 保存 Session 信息
  • Session 粘滞方案:利用 Nginx 能够作四层 Hash 或七层 Hash 的特性,保证用户的请求都落在同一台机器上
  • Session 后端集中存储方案:利用 Redis 集中存储 Session,Web 应用重启或扩容,Session 也无需丢失。

上面四种方案,优先推荐第四种。

固然第四种方案须要必定的开发工做量,前期还没改造的过程能够选择 第三种方案中间过渡。

好了,后面就要使用 Session 后端存储方案改造这个工程了,后面小黑哥再跟你们分享一下 spring-session

帮助

  1. 架构师之路-session一致性架构设计实践
欢迎关注个人公众号:程序通事,得到平常干货推送。若是您对个人专题内容感兴趣,也能够关注个人博客: studyidea.cn

相关文章
相关标签/搜索