Session是服务器用来保存用户操作的一系列会话信息,由Web容器进行管理。单机情况下,不存在Session共享的情况,分布式情况下,如果不进行Session共享会出现请求落到不同机器要重复登录的情况,一般来说解决Session共享有以下几种方案。
1、session复制
session复制是早期的企业级的使用比较多的一种服务器集群session管理机制。应用服务器开启web容器的session复制功能,在集群中的几台服务器之间同步session对象,使得每台服务器上都保存所有的session信息,这样任何一台宕机都不会导致session的数据丢失,服务器使用session时,直接从本地获取。
这种方式在应用集群达到数千台的时候,就会出现瓶颈,每台都需要备份session,出现内存不够用的情况。
原理:Terracotta的基本原理是对于集群间共享的数据,在当一个节点发生变化的时候,Terracotta只把变化的部分发送给Terracotta服务器,然后由服务器把它转发给真正需要这个数据的节点。这种方案可以看成是对第二种方案的优化。
优点:这样对网络的压力非常小,各个节点也不必浪费CPU时间和内存进行大量的序列化操作。把这种集群间数据共享的机制应用在Session同步上,既避免了对数据库的依赖,又能达到负载均衡和灾难恢复的效果。
2、session绑定
利用hash算法,比如nginx的ip_hash,使得同一个Ip的请求分发到同一台服务器上。
这种方式不符合对系统的高可用要求,因为一旦某台服务器宕机,那么该机器上的session也就不复存在了,用户请求切换到其他机器后么有session,无法完成业务处理。
3、利用cookie记录session
session记录在客户端,每次请求服务器的时候,将session放在请求中发送给服务器,服务器处理完请求后再将修改后的session响应给客户端。这里的客户端就是cookie。
利用cookie记录session的也有缺点,比如受cookie大小的限制,能记录的信息有限;每次请求响应都需要传递cookie,影响性能,如果用户关闭cookie,访问就不正常。但是由于
cookie的简单易用,可用性高,支持应用服务器的线性伸缩,而大部分要记录的session信息比较小,因此事实上,许多网站或多或少的在使用cookie记录session。
4、session服务器
session服务器可以解决上面的所有的问题,利用独立部署的session服务器(集群)统一管理session,服务器每次读写session时,都访问session服务器。
这种解决方案事实上是应用服务器的状态分离,分为无状态的应用服务器和有状态的session服务器,然后针对这两种服务器的不同特性分别设计架构。
对于有状态的session服务器,一种比较简单的方法是利用分布式缓存(memcached), 数据库等。在这些产品的基础上进行包装,使其符合session的存储和访问要求。
如果业务场景对session管理有比较高的要求,比如利用session服务基层单点登录(sso),用户服务器等功能,需要开发专门的session服务管理平台。
分布式 session 在并发的情况下,会出现 session 不同步的问题?
可以使用 tair 的乐观锁解决这个问题,当用户取得 session 后,并获得一个版本号。当更 新 session 的时候,版本号+1。如果在跟新 session 的时候版本号不一致,则不能更新。保证 session 的一致性
使用Session共享,也分为两种机制,如下:
1、粘性Session处理方式
原理:不同的Tomcat指定访问不同的主memcached。多个memcached之间信息是同步的,能主从备份和高可用。用户访问时,首先在Tomcat中创建Session,然后将Session复制一份放到它对应的memcached上。memcached只起到备份左右,读写都在Tomcat上。当某一个Tomcat挂掉之后,集群将用户的访问定位到备Tomcat上,然后根据cookie中存储的SessionID找到Session,找不到时,再去相应的memcached上去寻找Session,找到之后将其复制到Tomcat上。
2、非粘性Session处理方式
原理:memcached做主从复制,写入Session在从memcached服务器上,读取Session从主memcached,Tomcat本身不存储Session。
优点:可容错,Session实时响应。
实现方式:用开源的msm插件解决Tomcat之间的Session共享:Memcached_Session_Manager(MSM)
a. 复制相关jar包到tomcat/lib 目录下
JAVA memcached客户端:spymemcached.jar msm项目相关的jar包: 1. 核心包,memcached-session-manager-{version}.jar 2. Tomcat版本对应的jar包:memcached-session-manager-tc{tomcat-version}-{version}.jar 序列化工具包:可选kryo,javolution,xstream等,不设置时使用jdk默认序列化。
b. 配置Context.xml ,加入处理Session的Manager
粘性模式配置:
非粘性配置:
3、微服务架构下分布式Session管理方案
经过上文的分析,在微服务架构中,使用Session集中管理的方式维护微应用的Session是比较好的选择。因为在Session存储介质上,Redis要比Memcache合适,所以使用Redis来集中存放微应用Session更为合适。在Session管理实现方案上,Spring Session的实现思路适用性较高,但是代码量大,学习和维护成本高,所以笔者认为参照Spring Session的思路,自己开发一套轻量级的代码是比较好的选择。
经过设计,微服务架构中的Session集中管理示意图如下。
图5 Session集中管理方案示意图
1、参照SpringSession的实现,使用SessionFilter进行请求拦截,然后通过Request包装类接管Web服务器的Session管理。在Request包装类中,重写getSession方法,Session使用方法和过去一样,对使用者透明。
2、基于jedis开发一个分布式缓存SDK模块,用于Session共享模块和Redis中间进行通信,能够增加Session集中管理的可扩展性,如果需要支持其他的缓存服务器,对缓存SDK进行扩展开发即可。
3、搭建Redis集群用于存放微应用Session,以保证Session数据的高可用。Redis集群示意图如下。
集群中包含两个Master和两个Slave,两个Master对Session数据进行分片存储,而Slave可用于进行数据备份和读写分离。
5、Session持久化到数据库
原理:拿一个数据库专门用来存储Session信息,保证Session的持久化。
优点:服务器出现问题,Session不会丢失。
缺点:如果网站的访问量很大,把Session存储到数据库中,会对数据库造成很大压力,还需要增加额外的开销,维护数据库。