最近在读一本来自淘宝技术团队大牛的书,名字叫《大型网站系统与Java中间件实践》。开篇的章节详细地介绍了一个网站架构由小变大不断演进的过程,其中从单机架构升级到集群架构的过程中着重介绍了关于session同步问题, 这也是很多人在聊到分布式时绕不过去的话题。下面就整理下书中的内容,也算是做个读书笔记,方便以后参考。
做web开发的同学应该对session再熟悉不过,它是服务器分配给客户端的会话标识,浏览器每次请求会带上这个标识来告诉服务器我是谁,服务器会在内存中存储这些不同的会话信息,由此来分辨请求来自哪个会话。在单机部署的环境总,因为web服务器和session都是在同一台机器上,所以必然能找到对应的会话数据。但如果有2台web服务器(A和B)提供服务,假如第一次请求落到A上并创建了session,那么如何保证下次落到B的请求能读到session数据?
有以下4中常见的解决方案。
1、Session Sticky
这是最简单粗暴的 方法,核心思路就是让同一会话的请求都落地到同一台服务器上,这样处理起来就和单机一样了,我们可以在负载均衡上做一些身份识别并控制转发来达到这个目的。这样做的优势是能像单机一样简化对session处理,也方便做本地缓存,但缺点也是很明显的:
2、Session Replication
顾名思义,这是一种session复制的方案,核心思路就是通过在服务器之间增加session同步机制来保证数据一致。
看起来比第一种简单了很多,也没有第一种带来的缺陷,但在某些应用场景下还是会有比较严重的问题:
目前很多应用容器都支持这种同步方式,所以在集群规模和数据量比较小的时候还是一种很好的解决方案。
3、Session集中存储
这种方式的思路就是把所有的会话数据统一存储和管理,所有应用服务器需要对session进行读写都要通过session服务器来操作:
这种方案的好处是独立了session的管理,职责单一化,session服务器采用什么方式存储(内存、数据库、文档、NoSql等等),什么方式对外提供服务都是透明的。不会给应用系统和负载均衡带来额外的开销,不需要进行数据同步就能保证一致性,看起来应该是非常完美了,不过也有自己的一些小缺陷:
每种方案带有它独特的优势,同时也会带来相应的新问题,正所谓没有十全十美,只有适合才是最好的。总体来说,这种方案在应用服务器和会话数据量都很大的时候还是非常有优势的。
4、Cookie Base
这种方案是基于cookie的传输来实现的,核心思想很简单,就是把完整的会话数据经过处理后写入到客户端cookie,以后客户端每次请求都带上这个cookie,然后服务端通过解析cookie数据来获取会话信息,如下图所示:
这种方案简单明了,也没有前面几种方案带来的问题,但劣势也非常明显:
以上4种方案都是可行的方案,正如前面所说,每种方案各有优劣,不会十全十美,实际应用中要根据需求做权衡和取舍。这些都是属于比较通用的方案,我相信在真正的实践和落地过程中还会有其他问题出现,有经验的过来人或许会有一些另辟蹊径的“套路”,欢迎讨论交流。