假设网站部署在N台服务器上,可能是tomcat集群或者nginx集群,在集群之前有一个负载均衡服务器,使得用户对网站的访问会均衡地访问到服务器集群的各个节点上。
现在A用户开始访问网站,假设分配到b服务器上,那么如果A用户在session生命周期内,再次访问网站(用户在访问的过程中是随机切换到其他服务器),如何获得他的session呢?(因为可能会分配到其他服务器上,或者如何记得之前分配在哪个服务器上?)
这就是服务器集群session共享问题。
解决方案:
1. tomcat session复制
tomcat本身自带session复制功能,开启server.xml中的`cluster`节点,做相应的配置即可。参见Apache Tomcat 8 (8.0.26)。tomcat本身的session复制功能并不好用,官方文档也说方式只适合小集群:
This works great for smaller cluster but we don't recommend it for larger clusters(a lot of Tomcat nodes).
并且tomcat本身并发性能也并不太好。这种方式更加适合于对并发要求不高的小规模集群。
2. redis存储session
这种方案可能是用得最多的一种
直接配置tomcat的session管理,session直接让redis管理
主要的配置是在
修改tomcat的context.xml
<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />
<Manager className="com.radiadesign.catalina.session.RedisSessionManager"
host="localhost"
port="6379"
database="0"
maxInactiveInterval="120"/>
所有session都存在redis(redis集群)中,无论访问哪台服务器最终都会把session保存在redis中,然而redis集群是如何保证各个结点的数据一致性,对于这个需求是黑匣子,不必关心。
3. session cookie化
把原来存储在服务器磁盘上的session数据存储到客户端的cookie中去。
这样子,就不需要涉及到数据共享了。a客户端请求的时候,原来生成在服务器的数据生成到浏览器的cookie中,根据cookie中的数据识别用户。
这样子,在多台服务器负载均衡的情况下,即便第一秒请求是a服务器,第二秒请求是b服务器,都不需要管哪台服务器了。反正都是读取客户端上的cookie数据。
一般是把session数据按照自己定义的加密规则,加密后后存在cookie中。
数据保存在cookie中这种做法有好处,也有坏处。
好处是服务器的压力减小了,因为session数据不存在服务器磁盘上。根本就不会出现session读取不到的问题。
带来的弊端是:
网络请求占用很多。每次请求时,客户端都要通过cookie发送session数据给服务器。
另外,浏览器对cookie的大小存在限制。每个浏览器限制是不同的。
- Firefox和Safari允许cookie多达4097个字节,包括名(name)、值(value)和等号。
- Opera允许cookie多达4096个字节,包括:名(name)、值(value)和等号。
- Internet Explorer允许cookie多达4095个字节,包括:名(name)、值(value)和等号。
所以这种方案不适合高访问量的情况下,因为高访问量的情况下,每次请求浏览器都要发送session数据给服务器。一般一个cookie大小2k的样子。
要占用很多带宽了(服务器购买带宽是一个很大费用),成本增高。归纳为带宽性能,速度问题。
存储到cookie中去,第二方面是安全问题:把session数据放到客户端,一般session中存的都是重要性数据(帐号、昵称、用户id等),会存在安全问题。
了解到,淘宝以前用过这种方式,把session数据存储到cookie中,根据cookie来识别用户。
4. 粘性session
该种方式下,当用户发出第一个request后,被分配到某个节点,并记录该节点的jvm路由,以后该用户的所有request都会被绑定到这个jvm路由,用户只会与该server发生交互,这种策略称为粘性session。
优点是响应速度快,多个节点之间无须通信。
缺点是某个节点down掉后,用户就丢失了session。
5. 不使用session
这就是另外一种思路了,其实差不多,也提一下吧。
HTTP本身就是无状态的,应用服务器为了跟踪用户状态而强行加入了session。服务器为了保存用户状态就需要做额外的工作。
于是乎,Token-based的身份校验因其伸缩性而广受欢迎。在用户登录后,服务器返回一个token给用户,用户后续的请求都需要附带此token,服务器会校验该token来判断用户身份,进而完成具体业务(这里掠过不谈token的安全防护问题)。
Reference:
1. https://segmentfault.com/q/1010000003988125
2. https://www.zhihu.com/question/27085849
3. http://www.imooc.com/article/5087
4. http://www.cnblogs.com/wangtao_20/p/3395518.html
5. http://www.360doc.com/content/12/0302/10/7472437_191040410.shtml