大型网站之分布式会话管理
随着网站的功能和用户越来越多,单机器服务部署的Web应用已经不能再支持了。这时候就需要优化或调整架构,具体怎么优化,或先优化哪部分,这取决于网站的具体情况, 并非总是一个套路。
如根据使用情况得知,数据库压力大,则就可以先设施读写分离,分库分表,是垂直划分(按业务划分), 还是水平划分(如用户表数据量很多,可以按一定规则分表设计,表结构仍然相同)。如 Web 应用服务器压力大,可以增加一台服务部署应用, 即从单台服务变为集群。变为集群后,用户访问网站,到底是选择哪一台服务器呢?这就需要在应用服务器前增加负载均衡设备来解决。还有点就是会话 session 管理的问题,接下来会详细说明这问题。
具体的问题
当一个带有会话的 Http 请求到达 Web 服务器后,需要在请求中的处理 session 数据。问题在于,session 是保存在单机上的。假设我们是一个分布式集群,有应用 A 和应用 B,A 和 B 可能位于不同的服务器(集群),现在一位用户第一次访问网站,session 数据保存在应用 A 中。如果不做处理,怎么保障接下来的请求每次都请求到应用 A 呢? 如接下来用户又请求到了应用 B ,就会发现没有这位用户的 session 数据,这绝对是不能容忍的。
解决方案
解决方案有 Session Stick,Session 复制,Session 集中管理,基于 Cookie 管理,下面一一说明。
1,Session Stick
在单机情况,session 保存在单机上,请求也是到这台单机上,不会有问题。变成多台(集群,此时只是增加 Web 集群,并没有进行垂直划分,每台服务器具有相同的功能)后,如果能保障每次请求都到同一台服务,那就和单机一样了。 这需要在负载均衡设备上修改,保证用户每次都落到同一台服务器上。这就是 Session Stick,这种方式也会有问题:
-
如果某一台服务器宕机或重启,那么这台服务器上的 session 数据就丢失了。如果 session 数据中还有登录状态信息,那么用户需要重新登录。
-
负载均衡要处理具体的 session 到服务器的映射。
2,Session 复制
Session 复制顾名思义,就是每台应用服务,都保存会话 session 数据,一般的应用容器都支持。与 Session Stick 相比,sessioon 复制对负载均衡没有太多的要求。不过该方案的缺点是:
-
同步 session 数据带来都网络开销。只要 session 数据变化,就需要同步到所有机器上,机器越多,网络开销越大。
-
由于每台服务器都保存session数据,如果集群的session数据很多,比如90万人在访问网站,每台机器用于保存session数据的内容占用很严重。
这个方案靠应用容器来完成,并不依赖应用,如果应用服务数量并不是很多,可以考虑。
3,Session 集中管理
这个也很好理解,用一台专门的服务器管理 session 数据,每台应用服务都从专门的 session 管理服务中取会话 session 数据。可以使用数据库,NOSQL 数据库等。与 Session 复制相比,减少了每台应用服务的内存使用,同步 session 带来的网络开销问题。但缺点是:
-
读写session引入了网络操作,相对于本机读写session,带来了延时和不稳定性。如Session集中服务有问题,会影响应用。
4,基于 Cookie 管理
最后一个是基于 Cookie 管理,把 session 数据存放在 cookie 中,然后请求过来后,从cookie中获取session数据。虽然与集中管理相比,这个方案并不依赖外部的存储系统,读写 session 数据带来的网络操作延时和不稳定性,但用户可能会禁用 Cookie。它的缺点是:
-
Cookie有长度限制,这会影响session数据的长度。
-
安全性。session数据本来存储在服务端的,而这个方案是让session数据转到外部网络或客户端中,所以会有安全性问题。不过可以对写入Cookie的session 数据做加密。
-
带宽消耗。由于加了session数据,带宽当然也会增加一点。
-
性能消耗。每次Http请求和响应都带有Session数据,对于Web服务器来说,在同样的处理情况下,响应的结果输出越少,支持的并发请求越多。
总结
需要根据具体的实际场景做出合适的选择。这四种方案都是可用的,我个人比较倾向集中管理。