一、什么是session?什么又是cookie?他俩有啥联系和区别?java
二、为何要在多台服务器间进行session的共享同步?nginx
三、以及有哪些方法来实现这个同步?web
你们快搬板凳,老王开始扯淡咯~算法
1、session和cookie的缠绵与悱恻数据库
相信有盆友跟老王同样,曾经为session和cookie纠结过,或者如今正在为他们纠结。session在英文里的意思是会议,而cookie则是饼干。你说这个会议和饼干怎么就关联上了呢?(开会的时候能够吃饼干)浏览器
咱们先来看看百度百科的解释吧:tomcat
A、cookie:安全
Cookie, 有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(一般通过加密)。Cookie是 由服务器端生成,发送给User-Agent(通常是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一 网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)性能优化
B、session:服务器
在计算机中,尤为是在网络 应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,若是该用户尚未会话,则 Web 服务器将自动建立一个 Session 对象。当会话过时或被放弃后,服务器将终止该会话。
你们看懂了嘛?我打包票,确定仍是有盆友没看懂。老王本身是这么来理解他们的:
A、cookie:
浏览器请求服务器,服务器为了区别不一样的用户请求,就须要给他们打上标签,好比:发放一个访问令牌(access_token)给客户端。发放的过程是经过在HTTP请求返回的时候,经过设置HTTP的header:Set-Cookie来实现的。
以上就是我请求百度,他给我发放的cookie们。每个Set-Cookie里通常会含有设置的key=value、过时时间,以及域和路径。
当浏览器接收到这样的返回头之后,就把他稳妥当当的存起来,之后每次发送请求的时候,就会把他带上(具体还要看过时时间、做用的域和路径)。
这个cookie看起来像个什么东东呢?像不像有关部门给咱们发放的身份证?你去有关部门申请,他就把你的ID、性别、年龄等等信息给你打到一张叫作身份证的东东上,而后发给你。之后你每次去办点啥关键的事情,就须要带上这些cookie们。
一 般服务器会在浏览器里种上一些相似于访问令牌(access_token)、用户ID(user_id)等等的cookie,这样你一去访问对应的网站, 他就把你认出来了。特别,像java的服务器,还会种一些相似jsession_id的cookie,服务器采用必定的算法(好比随机算法),生成一个一 定长度(好比10字节)的字符串" angOwberup ",而后发放给浏览器: Set-Cookie:jssesion_id= angOwberup,当浏览器收到这个cookie之后,就跟拿到宝同样,好好的把这个key和value收藏了起来,之后每次去服务器请求都带上。
B、session:
与 此同时,服务器把这个字符串"angOwberup"做为key,把一个叫作User的类的一个实例user,设置好id、nickname等等信息以 后,放入了一个相似于map的容器里:map.put("angOwberup", user)。当浏览器请求来的时候,服务器就会getCookie("jsession_id"),把这个种在浏览器里的字符串取出来,而后用这个字符串 去map里找找,看看有没有对应的User对象:map.get(sessionId)。若是取到了,说明就找到了这个用户的id、nickname等等 信息,直接就能够在网页上显示:“老王你好,欢迎回来!”。若是没有找到,有可能就跳到登陆页面,让用户作登陆。
咱们把用户在必定时间内访问某个网站时,请求不一样页面的过程叫作一个会话,也就是session。在同一个session里,咱们能够记录用户访问的状态和信息。这样,那个相似于map的容器就是session管理器。
打 个形象的比喻,若是cookie是身份证,那session就是你的档案。你的全部信息都存放在档案里,有关部门(server)管理着你的档案。当你要 办重要的事情时,就须要拿着身份证去有关部门提取档案,有关部门查阅档案后,再看要不要给你办事儿。若是你作了坏事,他们就会往你的档案 (session)里写一些很差的东西;固然,若是你得了什么奖,也会往里面放。
这下,是否是有点清楚cookie和session有什么联系和区别了呢?再简要的总结一下:
A、cookie就是服务器发放给客户端的一些标识,让客户端记住每次请求的时候带上,以区分不一样的用户;
B、session是服务器存放在本身那里的用户相关的数据,用每次用户带来的cookie去提取出来,恢复一个以前访问的历史或者相关环境。
好了,有了上面的内容,接下来,咱们就须要讨论一下那个相似于map的session管理器了。
2、session的管理
上面说了,服务器用了一个相似于map的容器来管理session。那具体来看,这个map是怎么样来实现的呢?
不 同的服务器、不一样的语言框架都有不一样的实现。好比java的服务器,有的是用文件方式来存储的、有的是用内存cache的方式来存储的。老王还据说有的语 言的服务器将数据作加密,而后设置成cookie,存到了客户端(浏览器)。那这些实现方式都有哪些优缺点呢?咱们逐个来分析。(固然,有可能还有其余的 实现方法,老王可能不了解,不过大致思路类似,若有遗漏请指正)
A、文件方式:这种方式,将文件做为一个map,当新增一个数据的时候,就在文件中增长相似这样的一条数据:
angOwberup =>
data={"user":{"id":1,"nickname":"老王"}};
expiry="2016-10-0100:00:00"
(固然,具体实现的时候有多是用的二进制方式,而不是字符串)
这 种方式的好处,就是可以存储大量的用户session,使得这个session有效期能够比较长(好比:三个月用户不用登陆)。不过这个方式也有对应的问 题,就是文件操做比较麻烦。好比,有一个用户的session过时了,须要删掉这条记录,那这个文件就须要挪动或重写。
B、cache方 式:有好多web端的逻辑服务器都采用这种方式。这种方式好处很是明显,就是实现起来很是简单。将全部数据放入到内存cache中。若是有失效,直接内存 删除就能够了。不过带来的问题也很明显,当服务器重启之后,全部session都丢失了。或者当有大量用户登陆(也有多是遭受攻击),就会很快让 cache被充满,而后大量session被LRU算法淘汰,形成session的大量失效,使得用户须要反复登陆等操做。
C、 cookie方式:这种方式是最偷懒的方式。就是我服务器任何数据都不存,我把大家全部的客户端当作个人存储器,我就须要作一个加密和解密操做。固然这种 方式最大的好处就是实现极其简单(还有其余的好处,稍后再说),不过问题也是很明显的,就是客户端要记录大量信息,同时还要保证加密信息的安全。若是 session里要存放大数据,这种方式就不是很适合了。
除了上述说到的优缺点之外,A、B两种方式还有另一个问题,就是当我有不止一台服务器的时候,不一样服务器间的session数据共享就成问题了。
比 如,最初我只有一台服务器1,他的session里记录了user-1和user-2的数据。这个时候,我须要增长一台服务器2。当nginx把用户的请 求转发到服务器2的时候,他就傻眼了:用户带了一个jsession_id=angOwberup这个的cookie过来,而在他的session管理器 里却找不到这样一个session数据。那该怎么办?!(苦!恼!啊!)
所以,就出现了咱们文章一开始提到的问题:在分布式系统里,用户session如何才能实现同步?
3、session的同步
有了上面的状况,咱们就必需要去考虑,如何在多个服务器之间实现session同步这个操做。常见的作法有如下几种,咱们逐个来看看:
A、进程间通讯传递session数据。
这是最容易想到的一个方法。咱们在不一样的server服务里开一个socket,而后用socket来将相互拥有的session数据进行传递。我记得多年之前tomcat就是采用这样的方式来作的(已经好久没用过tomcat了,不知道如今是否还在这样使用)。
这 种方式的好处很明显,就是原理简单明了;坏处也很明显,就是同步合并过程复杂,还容易形成同步延迟。好比,某个用户在server-1登陆 了,server-1存储了这个用户的session,当正准备将数据同步给server-2的时候,因为用户访问实在是太快(飞通常的速 度),server-2还没收到server-1传来的session数据,用户访问就已经来了。这个时候,server-2就不能识别这个用户,形成用 户须要再次登陆。
并且,当有成千上万台服务器的时候,session同步就是一个噩梦:每个服务器都要将本身拥有的session广播给其余全部机器,并且还要随时进行,不能停歇…… (最后这些机器估计都是累死的)
B、 cookie存储方式。咱们在上面讲到了一个很偷懒的方式,就是把session数据作加密,而后存储到cookie中。用户请求到了,就直接从 cookie读取,而后作解密。这种方式真是把分布式思想发挥到了一个至关的高度。他把用户也当作分布式的一员,你要访问数据,那你就本身携带着他,每次 到服务器的时候,咱们的服务器就只负责解密……
对于session里只存放小数据,而且加密作的比较好(防止碰撞作暴力破解)的系统来说,这是一个比较好的选择。他实现超级简单,并且不用考虑数据的同步。
不过若是要往session里存放大数据的状况就不是太好处理。或者安全性要求很高的系统,也不是太好的一个方式(数据有被破解的风险)。
C、cache集群或者数据库作session管理。咱们也能够采用另一种架构来解决session同步问题,那就是引入统一session接入点。
我 们session放入到cache集群或者数据库中,每次请求的时候,都从他们中来获取。这样,全部的机器都能获取到最新的session数据。这种方案 也是不少中大型网站采用的解决方案。他实现起来相对简单(利用cache集群或者主从数据库自身的管理来实现多机的互备),并且效率很高,安全性也不错。
D、还有一种方式是从上面这种方式延展出来的,就是提供session服务。这个服务负责管理session,其余服务器每次从这个服务处获取session数据,从而达到数据的共享。
大 家若是仔细观察一下baidu或者google,你作登陆的时候,他们可能会让你跳到passport.baidu.com 或者accounts.google.com这两个域名之下。这两个就是他们用来作用户登陆和相似session管理的一个地方(因为以前只呆过 baidu,因此google并非很是清楚)。当一个访问请求来的时候,server就从cookie里取相似session_id的东东,而后用这个 东东去passport服务去请求用户的session数据。
这种方式的好处就在于:
A、能够很是方便的扩展用户登陆的数量以及存储数据的大小。当时在x度的时候,N亿用户的session都在这个系统里进行管理;
B、 方便作性能优化。若是用cache集群的方案,若是cache有机器坏掉,那么就会形成一部分用户session失效;若是用数据库方案,若是量太大,有 可能会出现性能问题。而这种方案在实现的时候,能够用cache和数据库结合的实现方式,保证高效和稳定。同时,针对一些接口,能够作性能的优化,提高查 询效率;
C、对外封闭,保证数据安全。这种方式还有一个好处,就是能够将加密算法、密钥等封闭在系统内部,对外只暴露接口,使得数据安全性更有保障。(涉及到用户信息的,都是隐私!)
不过,这种方式也有本身的问题,就是运维相对更复杂,有可能须要专门的团队去管理这些系统。
注:本文出自 https://www.toutiao.com/a6294758409293086977/