4种分布式Session的实现方式!老大直呼666...

前言

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

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

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

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

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

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

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

这个时候组长刚准备下班,看到我们这里有问题,于是过来了看了一下。简单了解的一下基本情况,很快就找到了问题的原因,然后在 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一致性架构设计实践

最后的话原创不易,都看到这了,点个「在看」再走呗,这是对我最大的支持与鼓励,谢谢你!往期推荐

最简单的6种防止数据重复提交的方法!(干货)


6种快速统计代码执行时间的方法,真香!(史上最全)

关注下方二维码,每一天都有干货!

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

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

相关文章

回溯算法n皇后问题_使用回溯算法的N Queen问题和解决方案

回溯算法n皇后问题N-皇后问题 (N - Queens problem) The n – queen problem is the generalized problem of 8-queens or 4 – queen’s problem. Here, the n – queens are placed on a n * n chess board, which means that the chessboard has n rows and n columns and t…

超简单的分布式ID生成方案!美团开源框架介绍

目录阐述背景Leaf snowflake 模式介绍Leaf segment 模式介绍Leaf 改造支持 RPC阐述背景不吹嘘,不夸张,项目中用到 ID 生成的场景确实挺多。比如业务要做幂等的时候,如果没有合适的业务字段去做唯一标识,那就需要单独生成一个唯一的…

教你写Bug,常见的 OOM 异常分析

在《Java虚拟机规范》的规定里,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生 OutOfMemoryError 异常的可能。本篇主要包括如下 OOM 的介绍和示例:java.lang.StackOverflowErrorjava.lang.OutOfMemoryError: Java heap spacejava…

池化技术到达有多牛?看了线程和线程池的对比吓我一跳!

这是我的第 82 篇原创文章作者 | 王磊来源 | Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG_Stone)情商高的人是能洞察并照顾到身边所有人的情绪,而好的文章应该让所有人都能看懂。尼采曾…

spearman相关性_Spearman的相关性及其在机器学习中的意义

spearman相关性This article is about correlation and its implication in the machine learning. In my previous article, I have discussed Pearson’s correlation coefficient and later we have written a code to show the usefulness of finding Pearson’s correlati…

被问哭了,一位小姐姐的阿里面经!(附部分答案)

这篇文章是一位 女读者 (加粗!太难得)的面试阿里的经历分享,虽然第二面就失败了,但是这样的经历对自己帮助应该还是很大的。下面的一些问题非常具有代表性,部分问题我简单做了修改(有些问题表述…

阿里《Java开发手册》最新嵩山版发布!

《Java 开发手册》是阿里巴巴集团技术团队的集体智慧结晶和经验总结,经历了多次大规模一线实战的检验及不断完善,公开到业界后,众多社区开发者踊跃参与,共同打磨完善,系统化地整理成册,当前的版本是嵩山版。…

递归转化成非递归过程_8086微处理器中的递归和重入过程

递归转化成非递归过程As we all know that a procedure is a set of instruction written separately which can be used any time in the code when required. A normal procedure execution includes calling of the procedure, shifting the control of the processor to th…

漫谈软件研发特种部队之中的一个

特种部队,是指进行特殊任务的部队,具有编制灵活、人员精干、装备精良、机动高速、训练有素、战斗力强等特点。 特种部队最早出如今二战期间。德国于1939年9月1日的波兰战役中首次投入了一种被称为“勃兰登堡”部队的特种部队作为德国突击波兰的先锋&…

不要一把梭了,这才是SQL优化的正确姿势!|原创干货

这是我的第 83 篇原创文章作者 | 王磊来源 | Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG_Stone)年少不知优化苦,遇坑方知优化难。——村口王大爷全文内容预览:我之前有很多…

PLSQL_性能优化系列10_Oracle Array数据组优化

2014-09-25 Created By BaoXinjian 一、摘要 集合是Oracle开发中经常遇到的情况,Oracle集合分为三种情况:索引表集合(index by table)、嵌套表集合(nested table)、可变集合(varry table)。 PL/SQL中没有数组的概念,他的集合数据类型和数组是…

IDEA 2020.2 重磅发布,动画级新功能预览!

Guide 关注了 IDEA 的官推,平时没事就会去看看有没有啥比较好的更新。今天下午看到IntelliJ IDEA 2020.2 都已经发布并且还支持了 Java15。然后,我就去官网简单看了一下新特性。单看新特性,这个新版本还是有一点香的。虽然我还木有升级到这个…

访问控制模型ACL和RBAC

2019独角兽企业重金招聘Python工程师标准>>> 1.ACL ACL是最早也是最基本的一种访问控制机制,它的原理非常简单:每一项资源,都配有一个列表,这个列表记录的就是哪些用户可以对这项资源执行CRUD中的那些操作。当系统试图…

最常见并发面试题整理!(速度收藏)

前言并发编程是面试中必问的知识点之一,所以本文整理了一些最为常见的并发面试题,一起来看吧~1. synchronized的实现原理以及锁优化?synchronized的实现原理synchronized作用于「方法」或者「代码块」,保证被修饰的代码在同一时间…

JavaScript中的嵌套事件处理(在鼠标移动事件上)

Multiple event handling is the secret ingredient of dynamic WebPages seen now-a-days. 多重事件处理是当今动态网页的秘密组成部分。 Now, let’s get started... 现在&#xff0c;让我们开始吧... Example Code 范例程式码 <html lang"en"><head&…

皮尔逊相关性_皮尔逊的相关性及其在机器学习中的意义

皮尔逊相关性Today we would be using a statistical concept i.e. Pearsons correlation to help us understand the relationships between the feature values (independent values) and the target value (dependent value or the value to be predicted ) which will furt…

磊哥最近面试了好多人,聊聊我的感受!(附面试知识点)

这是我的第 84 篇原创文章作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;一些读者可能知道&#xff0c;磊哥前段时间又回来上班了&#xff0c;详见《磊哥又滚回职场了...》…

M4 宏处理器

2019独角兽企业重金招聘Python工程师标准>>> M4 宏处理器 Brian W. KernighanDennis M. Ritchie Bell LaboratoriesMurray Hill, New Jersey 07974 翻译&#xff1a;寒蝉退士 译者声明&#xff1a;译者对译文不做任何担保&#xff0c;译者对译文不拥有任何权利并且不…

绝了,几款主流的 JSON 库性能对比!

本篇通过JMH&#xff08;Oracle官方测试框架&#xff09;来测试一下Java中几种常见的JSON解析库的性能。每次都在网上看到别人说什么某某库性能是如何如何的好&#xff0c;碾压其他的库。但是百闻不如一见&#xff0c;只有自己亲手测试过的才是最值得相信的。JSON不管是在Web开…

DWZ使用笔记

DWZ使用笔记 一、前言 在近期的一个项目中&#xff0c;引入了DWZ这个富client框架&#xff0c;算是一次尝试吧。期间也遇到不少问题&#xff0c;总算一一攻克了。特以此文记之。本人用的是dwz-ria-1.4.5Asp.net webform&#xff0c;写这篇笔记时最新版本号已经是1.4.6了。DWZ官…