解决集群后Session问题的几种方案
一、服务器集群中存在的Session问题
当我们的应用服务器从一台变成两台后,我们就会遇到Session问题,当一个带有会话标识的HTTP请求到了Web服务器后,需要在HTTP请求的处理过程中找到对应的会话数据(Session)。而问题在于数据是需要保存在单机上的。如下图所示,如果第一次访问网站是请求落到了左边的应用服务器上,那么我的Session就创建在左边的服务器上了,如果我们不做处理,就不能保证接下来的请求每次都落在同一边的服务器上了,这就是Session问题。
二、几种解决方案
1. Session Stick
这种方案本身非常简单,对于web服务器来说,该方案和单机的情况是一样的,只是我们在负载均衡服务器上做了“手脚”。这个方案可以让同样的Session请求每次都发送到同一服务器,非常利于Session进行服务器端的缓存。简单来说就是将每个Session与具体的应用服务器“绑定”,一个Session内的请求只发到对应的服务器上。
这种方式存在的问题:
- 如果某台服务器宕机或重启,那么这台机器上的数据就会丢失。如会话中有登录状态数据,那么用户就要重新登录了。
- 会话标识是应用层的信息,负责均衡服务器要将同一个会话的请求都保存到同一个web服务器,就需要应用层的解析,这个开销比传输层的交换要大。
- 负载均衡服务器变为了一个有状态的节点,要将会话保存到具体的web服务器的映射。内存消耗更大,容灾方面会更麻烦。
打个比方来说,Web服务器是我们每次吃饭的饭店,会话数据是我们的碗筷。要保证每次吃饭都用的是自己的碗筷的话,Session Sticky这种方式就类似于把碗筷放在某一家饭店,并且每次都是去这家吃。
2.Session Replication
类比到饭店吃饭,我们可以在每个饭店都放一副碗筷,那我们到哪个饭店吃都可以。这种方式不要求负载均衡服务器来保证同一个会话的多次请求必须到同一个服务器上,而web服务上多了同步Session到其他集群服务器上的操作。这样就能保证web服务器之间的Session一致性了。当然这种方式也存在着问题:
- 同步Session数据造成网络带宽的开销。只要Session数据有变化,就需要同步到其他服务器上,机器数越多,造成的开销越大。
- 每台web服务器都要保存所有的Session数据,如果Session数据很大(很多人同时访问),每台机器用于保存Session数据的内容占用就很严重。
这个方案是靠应用服务器复制Session内容来解决Session问题,但是不太适用集群机器数较多的场景,如果只有几台机器,用这个方案是可以的。
3.Session 数据集中存储
这种方案是把Session数据集中存储起来,然后不同的web服务器从同样的地方来获取服务器。存储Session数据的方式,可以用数据库,也可以用其他的分布式存储系统。这个方案解决了Session Replication方案中的内存问题,对网络带宽比也较好。那这种方案存在的问题是什么呢?
- 读写Session数据引入了网络操作,相对于本机的数据读取来说,问题在于存在时延和不稳定性,不过这种通信一般都是发生在内网,问题不大。
- 如果存储Session数据的机器出现问题,那么就会影响我们的应用。
当web服务器数量较大,Session数量较多的时候,集中存储Session方式的优势非常明显。
4.Cookie Based
Cookie Based方式是最后一种方案,这个方案对于同一个会话的不同请求也不限制具体的处理服务器。具体实现是将Session数据放在Cookie中,然后web服务器从Cookie中生成对应的Session数据。这就好比我每次都把自己的碗筷带在身上,这样无论我去哪家饭店吃饭都可以了。相比前面几种方案,这个方案不会依赖外部的存储系统,也不存在从外部系统获取、写入Session数据的时延和不稳定行了。当然了,同样存在不足:
- Cookie长度限制。cookie是有长度限制的,这样就限制了Session的数据长度。
- 安全性。Session本来是服务端的数据,而这个方案是将服务端数据放到了外部网络和客户端,因此存在安全性问题。我们可以对写入Cookie的Session数据加密,不过对于安全来说,物理上的不接触才是安全的。
- 贷款消耗。这里指的是数据中心的整体外部带宽的消耗。
- 性能影响。每个http请求都要处理Cookie并生成Session,对系统性能有一定影响。
三、小结
这4种方案都是可用的方案,不过对于大型网站来说Session Sticky和Session数据集中存储是比较好的方案,而这两个方案又各有优劣,需要在具体的场景中做出选择和权衡。