先来看一下什么是Session。
用户使用网站的服务,基本上需要浏览器与Web服务器的多次交互。HTTP协议本身是无状态的,需要基于HTTP协议支持会话状态(SessionState)的机制。而这样的机制应该可以使Web服务器从多次单独的HTTP请求中看到“会话”,也就是知道请求是来自哪个会话的。
具体实现方式为:在会话开始时,分配一个唯一的会话标识(SessionId),通过Cookie把这个标识告诉服务器,以后每次请求的时候,浏览器都会带上这个会话标识来告诉Web服务器请求是属于哪个会话的。在Web服务器上,各个会话有独立的存储,保存不同会话的信息。如果遇到禁用Cookie的情况,一般的做法就是把这个会话标识放到URL的参数中。
单台应用服务器
当一个带有会话标识的HTTP请求到了Web服务器后,需要在HTTP请求的处理过程中找到对应的会话数据(Session)。而问题在于会话数据是需要保存在单机上的。
在面对应用服务器集群时,如果我第一次访问网站时请求通过负载均衡设备落到了服务器A,那么我的Session就创建在服务器A上了,如果我们不做处理,就不能保证接下来的请求每次都落在服务器A上了。
应用服务器集群
1.SessionSticky
使负载均衡器能够根据每次请求的会话标识来进行请求转发。
需要在负载均衡服务器上保存会话到具体Web服务器的映射。
SessionSticky
这种方法非常简单,但是有以下几个问题:
1).如果有一台Web服务器宕机或者重启,那么这台机器上的会话数据会丢失。如果会话中有登陆状态信息,那么用户就要重新登录了。
2)..会话标识是应用程序的信息,负载均衡服务器要将同一个会话的请求都保存到一个Web服务器上的话需要进行应用层(OSI模型第7层)的解析,这个开销比第4层(传输层)的交换大。
3)..负载均衡器变成了有状态的节点,要保存会话到Web服务器的映射,比无状态节点内存消耗更大,容灾会更麻烦。
2.SessionReplication
Web服务器之间增加了会话数据的同步,应用服务器集群中的每一台服务器上都有一份会话数据。
SessionReplication
但是也带来了一些问题:
1)..同步Session数据造成了网络带宽的开销。只要Session数据有变化就需要同步,机器数越多,同步带来的网络带宽开销越大。
2)..每台Web服务器都保存所有额Session数据,在很多人同时访问网站的时候,每台机器用于保存Session数据的内容占用会很严重。
3.Session数据集中存储
不同的服务器从同样的地方来获取Session。会话请求经过负载均衡服务器后,不会被固定在同样的Web服务器上,而是放在了一个集中存储的地方。Web服务器使用Session数据时,也是从这个集中存储Session数据的地方来读取。
Session数据集中存储
这个方案解决了第一种方案的内存问题,也第二种方案占用网络带宽的情况要好。但是依然存在一些问题:
1)..读写Session数据引入了网络操作,相对于本机的数据读取来说,问题在于存在时延和不稳定性。
2)..如果集中存储Session的机器或者集群有问题,就会影响我们的应用。
4.CookieBased
把Session数据放在Cookie中,在Web服务器上从Cookie中生成对应的Session数据。
CookieBased
这个方案不会依赖外部存储系统,也就不存在从外部系统获取、写入数据的网络时延和不稳定性了。
不过依然存在不足:
1)..Cookie长度的限制。Cookie长度会限制Session数据的长度。
2)..安全性。Session数据是服务端数据,这个方案让服务端数据到了外部网络和服务端。
3)..带宽消耗。数据中心整体外部带宽的消耗。
4)..性能影响。每次HTTP请求和响应都带有Session数据。
小结
这4种方案都是可用的方案,不过对于大型网站来说,SessionSticky和Session数据集中存储是比较好的方案,而这两个方案又各有优势,需要在具体的场景中做出选择和权衡。