00:00
前面我们给大家分析了一下,在我们分布式系统里边,如果我们再来使用session会带来的一些问题,那接下来我们就来解决这些问题,那现在来解决第一种问题,那最简单的这种方式,如果我们是某一个服务处于集群状态,那么相当于这个服务呢,我们复制多份,由于我们有负载均衡机制,浏览器呢,第一次可能会访问它,第二次呢又会访问别的服务,那如果我们第一次访问它,它给session里边放的数据,我们第二次负载均衡到了别的服务,由于呢,Session是它的内存,别的服务用不到,那这种情况怎么办?好,那先来说这种情况。接下来呢,我们可以用第一种方案叫session复制,比如那现在呢,浏览器来访问我们两个不同的服务器,我们假设呢,现在都是商品服务,那现在由于第一次我们负载均衡来到第一个服务器,第一个服务器呢,如果想要用session session里边放数据,那都是在它的内存里边放,第二个服务器呢,也是放在它的内存里边,但我们想要无论我们去哪个服务器,我们都能拿到我们session里边的数据,即使第一次它里边放的,我们在第二次来到它也能取出,那怎么办呢?我们可以使用session复制,我们也成为session同步方案,就是呢,让这两个服务器之间互相同步session它GD之前保存了一个一,它保存了一个二,然后呢,它两个一同步,那就它保存了一二,它也保存了个ER2,这样做的话呢,我们无论去哪个服务器,我们呢,都相当于能拿到我们全量的session数据,这样我们就不担心。
01:40
负载均衡到哪个服务器了?但然这个优点呢,是我们tomcat原生支持的,我们稍微修改一下配置文件,我们好多tomcat之间他们就能互相复制session,但是呢,缺点就非常明显了,首先我们这个session同步他们是要网络传输,我们一是有延迟问题,二是占量,占用我们这个带宽,我们可能呢就压缩了我们整个业务的带宽,我们降低了我们业务的处理能力了。第三个我们很致命的问题,那就是在这儿,如果假设我们现在有100台tomcat,那每一个tomcat里边session都只存了1G的数据,那想要用这个同步方案来做的话,我想不管访问哪个tomcat都能访问到session里边的数据,那相当于其他tomcat都要保存剩下99个人的所有全量数据,那相当每一个toca至少都得有100G的内存才能将session整个全量保存过来,所以呢,这个受到内存限制,我们。
02:40
整个呢,服务器没法水平扩展很多,我不能好复制上好多个tomcat来进行使用,所以在我们这个大型分布式集群系统下,我们这种复制方案我们是不用的,我们在小型系统里边,诶就三五个to cat,我们想要使用的话呢,我们就简单配置一下也还可以,这是我们说的第一种问题,Session复制,然后呢,第二个我们呢,也可以让客户端自己来存储session,我们呢不存,其实呢,我们这个session就是想要给session里边存一些数据,比如数据KV也好,KV也好,我们呢,以后给服务器里边我们不存这个数据了,所以要我们保存的数据,比如浏览器登录成功了,好,我们将成功的用户以前放在session里边,现在不放了,我们直接呢命令浏览器保存在他自己里边,怎么命令呢?那就是浏览器可以保存在他的cookie里边,那这样以后下一次浏览器访问别的服务器了,我怎么知道你是哪个用户,因为我上一个服务器登录的。
03:40
库,我命令浏览器以cookie的方式,相当于一个银行卡的方式保存起来了,那接下来浏览器呢,访问我们这个服务器,每次呢,都带上它这个完整的cookie信息,那我们服务器呢,想要用哪些数据读取浏览器带来的cookie就行了,这就类似于我们每一个人都有很多的个人信息,然后呢,每一个人自己把自己的个人信息都装一个厚厚的档案袋,走到哪里?
04:08
你都把你的整个档案袋提上,然后让人家知道我们的工作经验,有哪些,我们家庭住址等等这些信息,这其实是一个非常不安全的操作,这是第一点,所以我们缺点呢,首先是不安全,第二个是我们HTP请求要携带我们大量的数据,那我们也浪费网络带宽,但优点呢,就是我们服务器不存储我们数据了,连session都不用了,那么还能节省一些内存,但这种方式呢,我们肯定不会使用,首先就是由于我们浏览器的cookie长度呢是有限制的,可能有些浏览器遵循的标准不一样,它的长度限制不一样,但是呢,它都不能保存大量的信息。其次呢,我们浏览器里边所有的cookie信息,我们F12我们都看得见,如果我们有一些关键数据,比如我们在这,我们来看一下我们的奥服务,我来F12,假设如果我们有这个关键数据存在这儿,那我们都能看到我们这些数据的一些内容信息,而且我们还能在这儿进行篡改,诶,我在这来得得得,我来添上几个东西。
05:08
所以呢,这一块呢,也是非常危险的。所以我们不会使用这种方案,这种方案呢,只是一个思路,大家知道一下就行,然后呢,我们可以使用这种方案,比如我们使用哈希一致性,这个一致性呢,就是利用了我们负载均衡机制,比如我们这个浏览器访问,我们这个浏览器呢,第一次访问呢,它落到了我们这个服务器上,比如落到我们一号服务器,只要浏览器不变,永远都是这个人访问,那我们可以利用它的这个IP的哈希一致性,只要是来源于同一个IP的访问的,那我们就永远给它定位到同一个服务器,我们也不给他跑到第二个服务器了,这样呢,这个服务器里边,它内存里边存的东西,我们无论多少次过来,只要是同一个用户,都会落到他的身上,那么就能取得到,所以这是我们利用哈希一致性,当然这个哈希一致性我们还可以结合我们的业务字段。
06:05
比如我们凡是456号这个用户,他的所有请求都落到这个服务器,凡是123这个用户的所有请求他都落到这个服务器,所以呢,我们可以利用这些哈希一致性来最终让它固定的同一个东西固定的落到同一个服务器,我们就可以不用管我们这个session了。所以呢,它的优点也很明显,我们只需要改负载均衡的相关配置,比如我们来改NG4,我们来让它做一个IP哈希,相当于利用IP的哈希一致性,同一个IP全部落到我们后台的某一个服务器上,而且是同一个服务器上。这样做的好处呢,我们可以易于水平扩展,我们无论是水平扩展多少个服务器,反正呢,最终我们都是哈希一致的,你过来呢,第一次落到这儿以后还是落到这儿,但是它的缺点呢也很明显,比如我们第一个请求我们落到这个服务器了,然后呢,这个服务器突然闪断了一下,我们重启了一下,我们session里边的数据清空了,那么这个服务器呢,相当于就没有保存数据了,我们这个用户只要下一次再过来,所有的数据呢都没了,他可能得重新登录一遍,所有东西都得重新做一遍,所以呢,这个也是很麻烦的,而且呢,如果我们这个水平要扩展,如果我们服务器固定了还好,但如果我们水平扩展,原来呢是两台服务器,现在呢,我们加到了四台服务器,那现在想要做哈希,那相当于重新得计算一下,假设我们以前做哈希最简单的方式,我们按照他的IP地址,我们假设得到一个整数型的哈希,如果只有两台服务器。
07:39
那我们可以对二进行求余操作,那么求到余数,如果余数是一,我们呢,就落到第一台服务器,如果没有余数,我们落到第二台服务器,但如果变成了四台服务器,那么相当于就要对四进行求余操作,如果呢,余一落到第一台服务器,余二落到第二台服务器,余三落到第三台服务器,没有余数,我们落到第四台服务器,所以呢,如果我们以水平的增减服务器,有可能就会导致我们重新哈希以后就又落不到他之前的服务器了。
08:12
当然呢,这种也没什么问题,而且后来呢,我们这种也用的比较多,因为基于我们这个session本来就是拥有有效期的,就算这一次由于水平扩展原因,或者服务器闪断原因,Session没有了。那就相当于浏览器关掉了呗,那我们就让用户重新再做一次登录,重新再做一次就行了,这是我们说的这种办法,当然还有我们另外一种办法。我们之前所有的问题出现的原因就是我们浏览器再来访问我们某些服务的时候,由于负载均衡机制,会跳跳到我们不同的服务器,第一次来到这儿,第二次来到这儿,而又由于我们这个session是每一个服务器各自存储在各自的内存空间的,所以导致我们跳到下一个服务器以后,我们上一个服务器session里边的数据它就用不到了。那怎么办呢?我们就可以让session统一存储,无论是你哪个服务器,哪个cat,以后呢,你的session都不要存到你的这个内存里边了,全部呢,大家可以去存到数据库,也可以存到RA,或者存一些速度更快的一些no circle中间件等等等等。
09:21
所以呢,我们可以使用这种方案,那这样的话,假设我们第一个请求,我们来到第一个服务器,这个服务器呢,想给session里边存一些数据,假设呢,这个session的ID卡号呢是123,然后呢,我们给123里边存了一数据,比如我们就叫456,我把这个数据呢,我们存到了red里边,那下次我们负载均衡,我们来到第二个服务器,我们把这个卡号带来了,是123,我们想要取它数据,如果以前是各自存各自的,肯定取不来,但现在呢,大家都去red里面存,去red里面取,所以这个服务器要取数据也去red里面取,然后呢,123对应的数据,我们之前存了456,所以也能取得出来,所以我们这种方式,我们就可以解决我们session共享的问题,我们是让后端统一存储session,这个优点呢就是我们没有安全隐患,不像我们利用cookie的方式,我们将所有session里边之前要存的数据让浏览器自己存,我们还可以串开来,但是我们如果用这种方式,那我们所有的。
10:22
啊,数据都是我们后台统一存储,浏览器肯定是没办法访问到的,只要我们保障了我们后台的这个ravis的安全,那就没有人能去篡改里边相关的数据,这是第一个,第二个我们水平扩展呢,也非常容易,我们无论web服务器有多少个,十个,100个,1000个,反正呢,大家都去我们这个red里边统一来进行存取,但red容量不够了,我们把red来做一个集群,每个里边存一点,每个里边存一点,我们最终呢,解决容量问题,我们只解决red就行了,包括如果我们这个web服务器就算重启宕机,下一次再启动了。
11:00
我们也session不会丢失,因为session呢都是在red里面存着,跟我们这个业务服务器宕机与否是没有任何关系的,但是呢,它的不足也很明显,因为如果我们自己是存到内存里边,我们负载均衡来过来,我们想从session中取数据,从内存中取数据是非常快的,这是第一个,第二个从内存取数据呢,我们直接取,也不需要网络交互,如果我们存到了red里边,我们想要从session里边取数据。那现在将session所有东西都存到red,我们还得连接red再来一次网络交互,那这呢就是他们的缺点,但是不管怎么说,我们最终呢使用我们这个session共享,要解决这个问题,我们可以选用两种方案,第一种是我们后台统一存储,第二种呢是我们做哈希一致性,但针对于我们这个业务,我们最终还是来选择我们后台进行统一存储,这样呢,我们就不关心我们web服务器该怎样水平扩展,我们不担心这个问题,我们也不担心服务器的宕机问题,而如果要统一存储,相当于我们就得修改我们这个原来的htp session里边的这些逻辑代码了。我们原来拿到的这个session调用它的set attribute,我们原来保存呢,这些都是保存在我们tomcat里边,它内部的这个session里边,它呢,其实保存的这个东西,我们来点过来,可以看一下,它调用这个this set attribute来调用KY6保存,它都是从manager里边拿到一个什么上下文这。
12:30
Session的保存呢,其实都是保存在我们这个内存里边的,因为我们看这attributes里边,它就是调用的这个put方法,这个attributes呢,它其实就是一个map,所以呢,如果我们想要后台统一存储,不存储在map,要存储到red里边,那么就得重新来修改我们原生API这个session的代码,当然好的一点是我们spring呢,早就意识到了这个问题,专门编写了一个框架叫spring session,它呢就能完美的解决我们这个session统一存储问题。
13:01
我们到时候呢,想要统一存储session,我们就整合使用spring session就行了,这是我们说的session共享的解决,当然这个解决的所有前提就是浏览器无论负载均衡到哪个服务器,都能带上我们上一个服务器给他发的银行卡,也就是我们是同域名情况下。如果是不同域名情况下,大家也能看到,那么之前呢,奥这个域名给他发的银行卡,我们来到了我们这个古ma没带奥的域名头,那么就已经没有了这个银行卡,所以针对这个问题。又该如何解决,这就是我们说的子玉的session共享问题,什么叫子域,我们现在呢,是来发送一个我们这个卡,这个卡呢,域名的作用域是also鼓励me.com,我们可以呢,让它放大我们这个域名的作用域,比如我们只要是鼓励卖点。com整个域名下的我们都能用,如果我来放大了以后,我们接下来在这我们来看刷新一下,诶我们发现呢,这一块我们这个卡就能拿到了。
14:10
当然我们是在浏览器在这儿修改的,不能这样修改,我们就应该让服务器一登录成功,第一次给他发卡的时候,就把这个域名呢默认给它放大,因为我们现在在这session里边set和t tribute,我们来说一下我们第一次使用session,第一次使用session相当于我们去银行第一次办业务,银行会创建一个银行卡,这都是tomca帮我们来做的事,创建完了以后会命令浏览器保存这个银行卡,好命令浏览器保存这个卡号,这个卡号呢就是我们说的这个解sessiond的cookie,好我们把这个效果拿过来,就是我们这个解ID这个cookie,然后呢,以后浏览器只要访问哪个网站,就会带上这个网站的所有cookie,以后浏览器访问哪个网站就会带上这个网站的cookie,所以呢,现在我们要。
15:11
解决我们这个子域之间来,我们各种域名之间,什么叫子域,那现在呢,鼓励me.com.com,这是呢,我们的富语名在它下边,我们有author点鼓励ma.com,还有呢,我们商品的,还有我们会员的,比如member的,包括还有我们这个订单的,比如我们叫order的点古励ma.com,我们会有很多的这些它父域名下边对应的子域名。所以呢,我们想要每一个无论访问哪一个域,我们这个卡号要都能同步过来的话,所以我们现在要做的唯一一件事情就是在发卡的时候,发卡的时候,即使是我们这个子玉系统发的卡,我们也让它的整个作用欲能作用到我们整个的负极域名,所以呢,我们可以让它发卡的时候,即使是。
16:06
紫玉系统发的卡,我们也能让咱们这个富裕直接使用,而这个卡它是怎么使用的,这其实是浏览器做的活,因为所有的cookie都是浏览器里边保存的,只要你指定了这个域名。是这个浏览器以后在访问你这个网站的时候,自动会从他浏览器里边取出所有cookie,是这个域名下的,发送请求的时候就会带上,比如我们这个杰森人ID,我们来看一下,我来只要访问这个古mail com,我无论是访问哪个请求,我们可以看一下,我们来访问我们的这个首页请求古mail.com,好,我们肯定呢,在请求头里边会带上我们这个cookie叫session ID,那前提就是我们这个cookie的域名一定要是属于我们这个域名系统的,所以呢,我们现在要做的两个问题,就是我们为了子玉这个session能共享,我们在发卡的时候一定要指定域名,发卡的时候主要就是指定域名,指定域名为副域名,要不然默认他发卡的时候,他发卡呢,其实是我们这个调用了response,有一个叫and cookie,那相当给响应里边添加cookie的方法。
17:24
好,我们可以看一下原生API,它即使是整节session ID这种东西也是response,我们拿到htb server response,我们这个response里边呢有一个方法,这个方法呢,它有一个叫and cookie,我们把这个response跟这一块呢重名了,我们现在呢就叫一个。So late response。好,我们现在把这个serve light response我来拿过来,如果我们做完事情以后,我们可以给它and一个cookie,我们可以给它创建一个cookie,所以这个cookie呢,有一个KV6 value6,我们这个key呢,比如就叫解session ID,然后呢,VALUE6就是我们这个值,但是呢,每一个cookie都有它的这个作用域,点一个我们可以set多,但是这个作用域呢,默认不说,如果我们不说默认的这个作用域,那就是我们浏览器,因为我们登录是在author这一块登录的,那我们给他的响应相当于我们是在author这个域名下,我们进行的响应,因为我们登录成功,我们登录成功以后呢,我们是跳转到我们还是我们这个author这个域名下,所以呢,我们这个。
18:35
Do麦相当于默认域名,就是我们当前的这个域名,所以如果我们发卡的时候把这个域名能改成他副域名就好了,但这个发卡又是我们tomcat默认自己发的,你第一次使用session它就自己发的。所以如果我们自己来写这一段逻辑还是非常麻烦的,那么下一节课呢,就可以完全整合spring来解决这个问题,那最终我们想要实现我们在also里边登录成功,我们的鼓励mail里边能显示这个用户信息,那么就是这样的原理,首先呢,浏览器会在会员服务里边登录成功,那会员服务呢,会将登录成功的用户存到session里边,但是呢,他存session的时候,我们不让他存到自己的内存里边,我们可以让它存到red里边。接下来呢,给我们浏览器发卡,发卡的时候呢,又让我们这个session对应的session ID,这个卡默认的作用域不能只是我们会员服务,而让它放大作用域,一放大作用域放大成鼓ma com以后,我们浏览器下一次访问任何服务,那我们都会带上我们这个cookie就要解session ID的,因为我们这个访问其他服务呢,都是其他子域名的。
19:50
嗯。所以带上这个解session ID以后,我们想要从session里面取东西,因为我们所有的服务session呢都统一用red进行存取,所以我们访问到了其他服务,其他服务就算要按照这个session ID取出session里边的数据,他也去red里边查,那么最终就实现后端统一存储,前端一个卡去任何地方通用,那我们就解决了我们整个session的跨域问题,那下一节课我们就来整合spring session来完成这件事情。
我来说两句