集群环境中的Session管理

集群环境中的Session管理

一、概述

本文首先按照以下顺序讨论集群环境中Session管理的常见手段,然后使用一个实例来展示如何使用Spring Session快速实现集群间Session共享。

  1. 使用cookie记录session
  2. Session sticky
  3. Session sticky + 文件或DB存储
  4. Session replication
  5. 专门的Session服务器,如redis或memcached来存储session

二、集群环境实现Session管理的手段

1. 使用cookie记录Session

结构如下:
cookie

利用浏览器支持的Cookie记录Session简单易行,可用性高,并且支持服务器的线性伸缩,因此,许多网站都或多或少地使用了Cookie来记录Session。
但是Cookie记录Session的缺点也比较明显:受Cookie大小限制、每次请求响应都要传输Cookie影响性能、用户关闭了Cookie会造成访问不正常等。

2. Session sticky

结构如下:
Session sticky
开启硬件或软件负载均衡的session sticky(或session affinity)功能,总是将源于同一IP地址的请求分发到同一台服务器上。这样的话,在整个会话期间,用户所有的请求都在同一台服务器上进行处理,即Session绑定在某台特定服务器上,保证Session总能在这台服务器上获取。
前端负载均衡可选手段:
① Round-robin DNS
② 基于硬件的负载均衡
③ 基于软件的负载均衡,如Nginx
④ Apache mod_proxy或者mod_jk

例如,Nginx反向代理实现Session sticky的两种方式:
① ip_hash:

upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
    server backend4.example.com;
}

② sticky指令:

sticky cookie name [expires=time] [domain=domain] [httponly] [secure] [path=path];

该指令导致某个客户端的所有请求被传递到同一台服务器。命令中的name即为nginx为这个客户端生成的cookie的名称。
注:1.5.7版本前也可以使用:sticky_cookie_insert这个命令。
另外,使用Apache + mod_proxy或mod_jk也可以开启session sticky功能。
Session sticky方式的缺点如下:
服务器宕机后session丢失;
如果前端还有代理,无法准确获取ip地址(即无法适用于CDN网络,以及前端还有代理的情况)

3. Session sticky + 文件或DB存储

这种方式很类似session sticky方式,区别在于服务器后台需要一个所有web容器(例如tomcat)实例都可以访问的NFS或SMB存储设备,web容器定时或不定时的将Session存储到文件或db存储上,可以提供比sticky Session更好的可用性。
例如,tomcat6以后即可结合Apache mod_proxy/mod_jk + + Persistent Session Manager + shared file store / JDBC store 开启这一功能。
此功能的缺点在于web容器一般无法保证Session数据被写入file store或db store的时机,因此这种方式只比上一种方式稍好一些。

4. (In-memory ) Session replication

结构如下:
Session replication
该方案简单易行,集群中的几台服务器之间同步Session对象,任何一台服务器宕机都不会导致Session对象的丢失,服务器也只需要从本机获取即可。
例如,tomcat就提供两种方式支持在tomcat集群的实例之间复制Session数据:集群内所有实例间拷贝 VS 只拷贝给backup服务器。
tomcat的Session replication结构如下:
tomcat Session replication
关于如何tomcat上开启session replication,请参考如下链接:
https://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html

注:这种方案也需要开启前端负载均衡的Session sticky功能。
该方案的缺点是,只适合集群规模较小的情况下。当规模较大时,大量的Session复制操作会占用服务器和网络的大量资源,系统不堪重负。

5. 专门的Session服务器,如redis或memcached来存储session

结构如下:
SessionServer
利用独立部署的Session服务器或集群(如memcache,redis)统一管理Session,应用服务器每次读写Session时,都访问Session服务器。这种方案实际上是将应用服务器的状态分离,分为无状态的应用服务器和有状态的Session服务器。
Java Web中使用这种方案,一般是通过实现一个servlet Filter拦截所有httpservletrequest,然后将HttpSession转换为自定义的Session并存储到Session服务器中。当然,根据DRY法则,你可以直接使用Spring提供的解决防范:Spring Session。
Spring Session自带Redis存储,自动转换HttpSession;支持WebSocket下保持Session活跃;支持在非Web请求的处理代码中,支持每个浏览器上使用多个session,这样就可以很容易地构建更加丰富的终端用户体;访问session数据,比如在JMS消息的处理代码中;也支持将Redis替换为memcache、GemFire等其他缓存手段。
关于如何使用Spring Session,可以参考如下链接:
http://www.infoq.com/cn/articles/Next-Generation-Session-Management-with-Spring-Session

三、简单实例演示Spring Session的使用

TODO

四、附录

1. Servlet与Session回顾

Servlet API提供HttpSession接口来管理Session。可以通过HttpServletRequest.getSession()来获取session。
调用getSession时,除了创建HttpSession对象外,还会向response中创建一个名为JSESSIONID的Cookie对象,值为生成的HttpSession的id。
如果浏览器关闭了cookie支持,那么还可以使用response.encodeURL(xxx)、response.encodeRedirectURL(xxx)来开启URL重写功能,此时浏览器的url后面会跟一个jsessionid=xxxxxx。

2.HttpSession常用方法

String getId(): 获取赋给session的唯一id
Object getAttribute(String name):获取指定属性的值。
其他操作属性的方法:
getAttributeNames(),removeAttribute(String name), setAttribute(String name, Object value)
setMaxInactiveInterval(int interval):设置session失效时间,以秒为单位

四、参考

http://www.cnblogs.com/edisonchou/p/3866819.html?utm_source=tuicool&utm_medium=referral
http://www.toxingwang.com/linux-unix/www/1904.html
http://docs.spring.io/spring-data/data-commons/docs/1.12.4.RELEASE/reference/html/
https://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html
http://www.datadisk.co.uk/html_docs/java_app/tomcat6/tomcat6_clustering.htm
https://www.mulesoft.com/tcat/tomcat-clustering

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论