session很快失效_一口气说出 4 种分布式一致性 Session 实现方式,面试杠杠的~

前言

公司有一个 Web 管理系统,使用 Tomcat 进行部署。由于是后台管理系统,所有的网页都需要登录授权之后才能进行相应的操作。

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

这时后端系统有两台服务,于是我们使用 Nginx 作为反向代理,整体架构图如下:

f4607b10143b0c1edfbe5767d433ed87.png

这个架构图想必大家应该比较熟悉,现在主流的 Web 系统应该都是这么部署。

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

这一测,出了大问题!测试小姐姐反馈,登录过后,没过一会又需要登录,操作好几次都是这样。

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

这个时候组长刚准备下班,看到我们这里有问题,于是过来了看了一下。简单了解的一下基本情况,很快就找到了问题的原因,然后在 Nginx 端修改了下配置,重启解决了问题。

分布式一致性 Session

解决完问题,组长坐下解释了问题原因:分布式一致性 Session

原先我们登录之后将会把用户登录信息放在 Session 中,用户每次操作首先先校验 Session 是否存在用户信息,如果不存在将会强制让用户先去登录。

原先架构的中我们只有一台应用系统,所有操作都在一台 Tomcat 上,这当然没有什么问题。

但是现在我们部署了两台系统,由于 Nginx 使用默认负载均衡策略(轮询),请求将会按照时间顺序逐一分发到后端应用上。

也就是说刚开始我们在 Tomcat1 登录之后,用户信息放在 Tomcat1 的 Session 里。过了一会,请求又被 Nginx 分发到了 Tomcat2 上,这时 Tomcat2 上 Session 里还没有用户信息,于是又要登录。

另外由于我们系统采用单点登录的方式,Tomcat2 登录之后会将 Tomcat1 登录信息失效,于是乎等到 Nginx 再把流量分发到 Tomcat1 时,Session 中用户登录信息已经失效,又要重新登录。

6a2d8a0ad175d63bfed124b63bdffd9f.png

知道了问题,当然想知道解决办法了,于是组长教了下分布式一致性 Session 四种解决办法,小黑哥给大家整理了一下:

08459793d6fb56f1cfc81f37af3d6b56.png

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

Session 复制

组长:

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

这时如果我们将 Tomcat1 的 Session 复制到 Tomcat2 上,后面 Nginx 将请求转发到 Tomcat2 上,由于 Tomcat2 存在 Session ,这时就不需要再重新登录了。

架构图如下:

1af154134e7f39c4658e9ec3416644df.png
Tomcat 的 Session 复制的配置,网上有比较多的例子,这里小黑就不再贴了,感兴趣的同学可以自行搜索一下。

小黑:

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

组长:

说的对,但是这种方式还是有很多缺点。

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

第二,我们的例子就只有两台机器,这个复制性能还可以。但是假设我们有 N 台机器,那么每次复制都要复制给 N-1 台机器,如果机器很多,可能会形成网络风暴,复制性能也会呈指数级下降。

第三, Tomcat 需要保存所有的 Session 数据,这个方案的 Session 存储在内存中,容易受到机器的总内存的限制。我们没办法通过加机器的方式水平扩展,我们能做的方式就是加大机器内存。但是机器内存越大,价格真的很贵!!!

所以不推荐使用这种方案。

Session 前端存储

小黑:

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

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

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

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

架构图如下:

81377cf0b94eadef4eb6f2765e923d7d.png

组长,欣赏看了一下我:

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

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

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

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

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

所以这种还是不怎么常用,不过也是一种思路。

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

Session 粘滞(Sticky Sessions)

组长:

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

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

Nginx 会使用请求者的 IP 来做 Hash,然后分发到一台机器上,这样可以保证同一 IP 的请求都落在同一台 Tomcat 上。

架构图如下:

2314553f717a7328c802bd4dfceb346f.png

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

架构图如下:

6155aab81bc7d53e507083d2ee446f63.png

小黑:

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

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

另外后面如果两台机器扛不住,我们还可以水平扩展,再加机器,只要修改 Nginx 配置即可。

组长:

你说的这几点都很正确!

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

另外如果 Tomcat 重启,Session 由于是放置在内存内存中,这一部分的 Session 将会丢失,这就导致这部分用户将会重新登录。

最后,如果我们临时再加机器,修改完 Nginx 配置,重新启动之后,Nginx 将会重新计算 Hash 分发请求。

这种情况就会导致有一部分用户重新路由到一台新机器上,由于没有 Session,又需要重新登录了。

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

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

不过后面我们还是改成下面这种方式。

后端集中存储

组长:

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

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

不过由于 Session 需要过期失效的特性,不需要持久化保存,所以这里我建议使用 Redis 来保存。

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

72c7444d9e887683df73c00caa3b60bb.png

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

另外后期如果应用可以直接水平扩展。

如果后面应用的请求量很大,一台 Redis 扛不住了,那我们可以其实可以做集群扩展,根据缓存 Key 做路由。

小黑:

对对,这种方式好~

组长:

你不要高兴的太早,我们使用这个方案需要付出一定的代价的。

首先我们每次请求都需要调用一次 Redis ,这就增加一次网络的开销。

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

所以说,这个方案有利也有弊,当然对于我们的场景来说,利大于弊。

小黑:

恩,好像是这样的。

组长:

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

小黑:

老大, !

组长拍了拍小黑的脑袋:

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

8febd9c1912367858ef7e9d16b743c87.gif

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

小黑:

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

总结

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

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

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

当然第四种方案需要一定的开发工作量,前期还没改造的过程可以选择 第三种方案中间过渡。

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

a8d27addeaa96f78bf00cb0dc635243d.png
作者:楼下小黑哥
链接:https://www.cnblogs.com/goodAndyxublog/p/13327412.html#4634068
来源:博客园

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/261862.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

定义动画名字html,CSS3 animation-name属性怎么用?

css3 animation-name属性是用来检索或设置对象所应用的动画名称,必须与keyframes配合使用,因为动画名称由keyframes定义 ;如果有多个属性值,可以用逗号进行分隔。css3 animation-name属性作用:animation-name 属性为 k…

线程中如何使用对象_多线程中如何使用gdb精确定位死锁问题

在多线程开发过程中很多人应该都会遇到死锁问题,死锁问题也是面试过程中经常被问到的问题,这里介绍在c中如何使用gdbpython脚本调试死锁问题,以及如何在程序运行过程中检测死锁。首先介绍什么是死锁,看下维基百科中的定义&#xf…

html中如何把两行合并单元格,css合并两列单元格内容

用纯DIVCSS做一个两行两列的表格,但第二列中两行怎么在html里把一行中的两列合并世界最不可以相信的话,就是从女人嘴里说出的话〃如上图,怎么做出上面图中的效果,分享大神详解CSS表格单元格占两行可以参考以下的代码: 单元格占两行…

ASP.NET MVC 实现二级域名(泛域名)

自从微软发布 ASP.NET MVC 和routing engine (System.Web.Routing)以来,就设法让我们明白你完全能控制URL和routing,只要与你的application path相结合进行扩展,任何问题都迎刃而解。如果你需要在所处的域或者子域处理数据标记的话&#xff0…

list和tuple

2019独角兽企业重金招聘Python工程师标准>>> list Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。 比如,列出班里所有同学的名字,就可以用一个list表示: >…

springboot数据源不正确_Spring MVC 到 Spring Boot 的简化之路

Spring全家桶笔记:SpringSpring BootSpring CloudSpring MVC​shimo.im01 背景从Servlet技术到Spring和Spring MVC,开发Web应用变得越来越简捷。但是Spring和Spring MVC的众多配置有时却让人望而却步,相信有过Spring MVC开发经验的朋友能深刻…

MapXtreme 包含所有自带坐标系一览

CoordSys 对象包含关于 X 和 Y 坐标如何与其在 Earth 上的位置相关联的基本信息。 每个 Geometry 或 Map 对象都有一个关联的坐标系。 CoordSys 对象包含对坐标系的详细说明。 CoordSysFactory 类提供了各种用于创建不同 CoordSys 对象的方法。 所有 CoordSys 对象都是只读的&a…

如何学习streamdecoder类_2019年终巨献:一份拿下了阿里、网易、滴滴等大厂offer的学习笔记...

2019仅剩最后二十天,回顾今年初遇“寒冬”时,自己也挺慌的,但是经历过这么多次面试后,我才“醒悟”,所谓的“寒冬”,“冻死”的都是“衣服穿的少的”。年末了在这里做一个年度总结,今年面试了不…

自定义控件的构建(12)

Share 前面讲了模板的构建&#xff0c;我们忽略了一个细节&#xff0c;如果接触ASP.NET时间不长的话&#xff0c;一般都会看到数据表达式是<%#Eval(‘Name’)%>这种形式的&#xff0c; 那么我们为什么用<%#Container.Name%>这种形式呢&#xff0c;其实前者是ASP.NE…

insertAfter()

<div id"b">bbbbbbbbb</div> <div>dddddd</div> JavaScript window.οnlοadfunction(){var a document.createElement("span");var b document.createTextNode("cssrain");a.appendChild(b);var mubiao document.getE…

学计算机等级考试电脑版软件,计算机二级考试宝典电脑版

计算机二级考试宝典电脑版是一款专业的二级计算机内容学习软件。该软件由武汉大学团队真情研发&#xff0c;软件包含选择题1600道&#xff0c;非选择题109套&#xff0c;成功实现了考点和重点的全面覆盖式学习目的&#xff0c;对学生们学习起到了巨大的帮助。该版本是通过安卓模…

mysq进阶

学习资料&#xff1a; 官方文档&#xff1a;http://dev.mysql.com/doc/refman/5.0/en/tutorial.html 1.存储过程&#xff1a; 优点&#xff1a;业务逻辑封装在存储过程中&#xff0c;容易维护&#xff0c;执行效率也高。 缺点&#xff1a;不同的数据库功能函数等不一样&#xf…

HTML使用vue的 event,vue-js 特殊变量$event常识

背景如果我们要阻止默认事件&#xff0c;在 chrome 等浏览器中&#xff0c;我们可能要写一个&#xff1a;event.preventDefault();而在 IE 中&#xff0c;我们则需要写&#xff1a;event.returnValue false;jquery &#xff0c;跨浏览器的实现&#xff0c;我们统一只需要写&am…

创建非矩形的Windows 窗体

创建非矩形窗体的过程包含三个步骤&#xff1a;• 创建一个作为窗体图面的位图。&#xff08;一种有效的方式是&#xff0c;您可以从矩形中“裁剪掉”所需的窗体形状。&#xff09;• 创建Windows 应用程序项目&#xff0c;将其属性设置为移除标题栏并使用位图作为窗体背景。•…

ExtJs6 Desktop Demo 修改测试

一直用Extjs4&#xff0c; extjs6 的变化较大&#xff0c;这几天有兴趣研究一下&#xff0c;把自带的Demo的desktop做了些修改&#xff0c; 1.首先下载安装sencha cmd 2.然后 需要生成新项目 用sencha cmd 命令如下&#xff1a; sencha -sdk E:\ext-6.0.0 generate app linb…

包含html语言的超链接标记的网页_零基础入门 HTML 的 8 分钟极简教程

在今天&#xff0c;前端工程师已经成为研发体系中的重要岗位之一。可是与此相对的是&#xff0c;极少大学的计算机专业愿意开设前端课程&#xff0c;大部分前端工程师的知识&#xff0c;也都是在实践和工作中不断学习的。最近收到很多同学的后台留言&#xff0c;说希望多推出一…

mongodb模糊查询_AWS 回击了!推出兼容 MongoDB 的 DocumentDB

2018 年 10 月&#xff0c;MongoDB 将其开源许可证从 GNU AGPLv3 切换到 Server Side Public License(SSPL)&#xff0c;并明确指出之所以会更改开源协议是因为部分云计算公司在使用 MongoDB 的时候没有遵循其开源协议。2019 年 1 月 9 日&#xff0c;AWS 宣布推出 Amazon Docu…

琴岛学院计算机应用技术,我院计算机工程系成功晋级“中国高校计算机大赛-网络技术挑战赛”全国总决赛...

2017年7月22日&#xff0c;由教育部高等学校计算机类专业教学指导委员会、教育部高等学校软件工程专业教学指导委员会、教育部高等学校大学计算机课程教学指导委员会和全国高等学校计算机教育研究会联合主办的“中国高校计算机大赛”首届网络技术挑战赛于济南大学举办。青岛理工…

Android L 的 Tint(着色)

Tint 是什么&#xff1f; Tint 翻译为着色。 着色&#xff0c;着什么色呢&#xff0c;和背景有关&#xff1f;当然是着背景的色。当我们开发 App 的时候&#xff0c;如果使用了 Theme.AppCompat 主题的时候&#xff0c;会发现 ActionBar 或者 Toolbar 及相应的控件的颜色会相应…

《从零开始学Swift》学习笔记(Day 66)——Cocoa Touch设计模式及应用之通知机制...

原创文章&#xff0c;欢迎转载。转载请注明&#xff1a;关东升的博客 通知&#xff08;Notification&#xff09;机制是基于观察者&#xff08;Observer&#xff09;模式也叫发布/订阅&#xff08;Publish/Subscribe&#xff09;模式&#xff0c;是 MVC&#xff08;模型-视图-控…