会话跟踪
我们知道在单机条件下session机制的通过cookie或者Url重写完成的,具体的做法是在用户第一请求到getSession方法时创建session并将创建cookie和jsessionid(String字段用来标识session),并把行用页面内所有的URL改写(在尾部家伙snag了jsessionid),然后发送到客户端。客户端再次请求(包含了是否允许cookie的信息),这次请求是已经被服务器做了URL重写了,所以会话被跟踪了。在服务器接受本次请求的时候,会判断 cookie是否被客户端浏览器接受,如果cookie不被接受,那么继续用URL重写来达到会话跟踪,如果cookie被接受那么首选用cookie实现会话跟踪。
Session数据结构
在servlet/jsp中,容器是用何种数据结构来存储session相关的变量的呢?
我们猜测一下,首先它必须被同步操作,因为在多线程环境下session是线程间共享的,而web服务器一般情况下都是多线程的(为了提高性能还会用到池技术);其次,这个数据结构必须容易操作,最好是传统的键值对的存取方式。
那么我们先具体到单个session对象,它除了存储自身的相关信息,比如id之外,tomcat的session还提供给程序员一个用以存储其他信息的接口(在类org.apache.catalina.session. StandardSession里):
- public void setAttribute(String name, Object value, boolean notify)
protected java.util.Map |
attributes The collection of user data attributes associated with this Session. |
然后其attribute属性是一个Map结构,所以很显然线程安全的Map结构我们首选ConcurrentHashMap作为其具体的对象,这是java的concurrent包里的一个类。它刚好满足了我们所猜测的两点需求:同步与易操作性。
那么tomcat又是用什么数据结构来存储所有的session对象呢?果然还是ConcurrentHashMap(在管理session的org.apache.catalina.session. ManagerBase类里):
protected Map<String, Session> sessions = new ConcurrentHashMap<String, Session>(); |
具体原因就不必多说了。至于其他web服务器的具体实现也应该考虑到这两点。
集群环境下的Session机制
现在由于互联网的日益发展,很多网站的访问量也日益的增大,单机服务器和数据库已经不能承受我们网站的访问压力,所以现在的系统都是做成了分布式集群以解决大并发大数据量的要求,比如淘宝就是一个非常经典的例子。那么问题来了,一个客户端发出的多条请求被多态服务器处理,对于客户端的传过来的cookie或url重写的请求,我们如何在分布式多态机器上面实现session共享呢?
一般情况下session不可以跨服务器存在,下面给出几种session共享的方式:
第一种,客户端解决方法.把session加密后存在cookie中,每次session信息被写在客服端,然后经浏览器再次提交到服务器.即使两次请求在集群中的两台服务器上完成,也可以到达session共享.这种解决方法的优点是session信息不用存放在服务器端,大大减轻了服务器的压力.另一个优点是一个session中的两次或多次请求可以在一个群集中的多个服务器上完成,可以避免单端故障.目前,淘宝是采用的这种解决方案. 基于Cookie的Session共享 这个方案我们可能比较陌生,但它在大型网站中还是比较普遍被使用。原理是将全站用户的Session信息加密、序列化后以Cookie的方式,统一种植在根域名下(如),利用浏览器访问该根域名下的所有二级域名站点时,会传递与之域名对应的所有Cookie内容的特性,从而实现用户的Cookie化Session 在多服务间的共享访问。 这个方案的优点无需额外的服务器资源;缺点是由于受http协议头长度的限制,仅能够存储小部分的用户信息,同时Cookie化的 Session内容需要进行安全加解密(如:采用DES、RSA等进行明文加解密;再由MD5、SHA-1等算法进行防伪认证),另外它也会占用一定的带宽资源,因为浏览器会在请求当前域名下任何资源时将本地Cookie附加在http头中传递到服务器。
第二种,提供一个群集保存session共享信息.其他应用统统把自己的session信息存放到session群集服务器组.当应用系统需要session信息的时候直接到session群集服务器上读取.这种方式具有第一种方式的第二个优点,现在可能淘宝也在用这种方式,他们使用具体的session共享框架目前还不知道
有一个哥们在研究bboss的会话共享框架:
bboss会话共享框架,快速实现集群节点间会话共享和跨域跨应用会话共享,实现与具体容器无关,能够统计在线会话数,还能在统一监控中心管理应用会话(删除会话,查询会话数据等)
第三种,配置负载均衡服务器,让用户的一个session在一个服务器完成.定时的备份session信息到salve上面.一台服务器down掉后,通过均衡服务器透明把用户的请求转发到群集中的其他服务器上,此时需要从salve上读取备份的session信息. 但是这种方式个人感觉比较扯,这种方式的意思就是让服务器保存特定用户的session然后让用户每次都访问这台服务器,也就不存在session共享的问题了,同时这台服务器还有salve作为备份,一旦这台挂掉了,那么就要器Salve上。
发表评论