刚电话面完,感觉要总结啊,心虚的很。
简历是在官网实习投的,后面好像获取了内推资格,然后完成了测评和笔试,当晚做完第二天上午10点左右就有显示杭州的座机过来,犹豫一下接了直接说杭州的阿里巴巴,有没有时间谈一下,改约到下午,忐忑一中午,大概2点多再打过来的,于是开始了:
自我介绍:基本信息,刚说到java web开发方面的网上商城,他就明显感兴趣,针对session问的很具体,感觉他是拿着我的简历问的,因为出现的都是我简历上有写出来的技术,比如el和分页什么的,问我session的原理,和cookie的区别,为什么购物车要用session,如果服务器重启缓存的数据怎么办,如果一个用户访问多个服务器,怎么可以把它sessionId同步到所有的服务器中,应该就是这个问题整的我理解不上来,其实他解释的很清楚,但是问题我不理解,其实就是被问懵了感觉,我傻到说不然是转发?他要的答案应该是说session同步的问题
贴一下我事后查找的补救:
问题:最初我只有一台服务器1,他的session里记录了user-1。这个时候,我需要增加一台服务器2。当nginx把用户的请求转发到服务器2的时候,他就傻眼了:用户带了一个jsession_id=angOwberup这个的cookie过来,而在他的session管理器里却找不到这样一个session数据。那该怎么办?!(苦!恼!啊!)因此,就出现了我们文章一开始提到的问题:在分布式系统里,用户session如何才能实现同步? 即,如何实现session的共享?
为什么有session?
首先大家知道,http协议是无状态的,即你连续访问某个网页100次和访问1次对服务器来说是没有区别对待的,因为它记不住你。
那么,在一些场合,确实需要服务器记住当前用户怎么办?
原理很简单,假设你访问网页时就像逛澡堂,第一次进去你是没有钥匙的,这个时候你交了钱服务台就分配一把钥匙给你,你走到哪里都要带上,因为这是你身份的唯一标识,接下来你用这把钥匙可以去打开一个专有的储物柜存储你的衣物,游完泳,你再用钥匙去打开柜子拿出衣物,最后离开游泳池时,把钥匙归还,你的这次游泳的过程就是一次session,或者叫做会话,在这个例子中,钥匙就是session的key,而储物柜可以理解为存储用户会话信息的介质。
那么在web server中如何实现session呢?想必看了上面的例子你会很容易理解,主要是解决两个问题,一个是钥匙的问题,一个是存储用户信息的问题。对于第一个问题,即什么东西可以让你每次请求都会自动带到服务器呢?如果你比较了解http协议,那么答案一目了然,就是cookie,如果你想为用户建立一次会话,可以在用户授权成功时给他一个cookie,叫做会话id,它当然是唯一的,比如php就会为建立会话的用户默认set一个名为phpsessid,值看起来为一个随机字符串的cookie,如果下次发现用户带了这个cookie,服务器就知道,哎呀,刚刚这位顾客来了。
剩下的是解决第二个问题,即如何存储用户的信息,服务器知道会话id为abc的用户来了,那abc想存储自己的私人信息,比如购物车信息,如何处理?这个时候可以用内存、也可以用文件,也可以用数据库了,但有个要求是,数据需要用用户的会话id即可取到,比如php就默认会把会话id为abc的用户会话数据存储到/tmp/phpsess_abc的文件里面,每次读取都要反序列化程序可以理解的数据,写的时候又需要序列化为持久的数据格式。
如何实现session的共享
这个博客讲的不错,借鉴引入【https://www.toutiao.com/a6294758409293086977/】:
A、进程间通信传递session数据。我们在不同的server服务里开一个socket,然后用socket来将相互拥有的session数据进行传递。
好处在于原理简单明了;坏处在于同步合并过程复杂,还容易造成同步延迟。
比如,某个用户在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管理的一个地方。当一个访问请求来的时候,server就从cookie里取类似session_id的东东,然后用这个东东去passport服务去请求用户的session数据。
好处:A、可以非常方便的扩展用户登录的数量以及存储数据的大小。
B、方便做性能优化。如果用cache集群的方案,如果cache有机器坏掉,那么就会造成一部分用户session失效;如果用数据库方案,如果量太大,有可能会出现性能问题。而这种方案在实现的时候,可以用cache和数据库结合的实现方式,保证高效和稳定。同时,针对一些接口,可以做性能的优化,提升查询效率;
C、对外封闭,保证数据安全。这种方式还有一个好处,就是可以将加密算法、密钥等封闭在系统内部,对外只暴露接口,使得数据安全性更有保障。(涉及到用户信息的,都是隐私!)
问题:运维相对更复杂,有可能需要专门的团队去管理这些系统。当然,除了上述的一些方式以外,还有其他的手段(比如,在入口nginx处对用户cookie做一致Hash,将某一用户分配到固定机器)。
大概就是这样了,问了解决方法和工作规划:
关键词记录:1)session托管的redies
2)集合的运用、多线程、hashmap[map]
3)nlo网络请求[这个没听清]
4)jvm内存机制、堆栈
5)servlet、Tomcat、dbutils、分布式、持久化
6)着重应用场景,即为什么要在这里用这个、明白为什么,带着问题和怀疑的态度去解决实践问题。
这篇博客没写完就受到阿里的回复了,效率高的惊人啊,发现简历上的东西一定要弄懂,人家就是照着简历的一个点深挖的,要努力呀!努力!!!