大型网站的业务繁多,于是就有多个子业务、子站点,对于某些热门子站点其web 服务器也有很多台。 网站的交互过程中很多状体需要在各个系统、节点中穿梭。 有一级域名,二级域名,三级域名,系统的各个功能模块分布在不同的域名,同一域名的也有可能分布在不同省份的服务器或者同一省份的不同的服务器中,同一省份的的服务器可以通过内部局域网访问。在系统中,现在需要所有功能模块共享用户同一次会话中的私有数据。 那么如何去管理这些状态呢 ? 1. cookie 2 session
1. session 和 cookie
Cookie是客户端的存储空间,由浏览器来维持。具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于才服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上还有其他选择,比如说重写URL和隐藏表单域。
如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。
如果设置了过期时间(setMaxAge(60*60*24)),浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。(在IE下测试通过)
2. 如何同步和管理用户的状态呢 ?
1 基于web服务器间的session复制
这是当前成熟的、老的方案,很多小型网站在采用。原理是:在一台web服务器发生session变化的时候,web服务器自动同步复制到另外的web服务器上。就java领域而言,即在调用session.setAttribute()方案的时候会触发session复制
但是缺点明显:当web服务器增多或者是遇到某些session复制性能不高的web服务器时,多web服务器间的session复制将是很大的性能开销。
2,基于cookie的管理方式。从大型网站的设计原则来看,其中有一条就是减少session的使用,能用cookie的尽量用cookie。
3、 基于session server方式。 自己去搭建session server, 让用户session在自己系统中管理起来。 当然也可以利用现有机制: 基于state
我们现在来看看在集群环境中,Session管理的几种常见手段:
①Session复制:该方案简单易行,集群中的几台服务器之间同步Session对象,任何一台服务器宕机都不会导致Session对象的丢失,服务器也只需要从本机获取即可。但是,该方案只适合集群规模较小的情况下。当规模较大时,大量的Session复制操作会占用服务器和网络的大量资源,系统不堪重负。
②Session绑定:利用负载均衡的源地址Hash算法,总是将源于同一IP地址的请求分发到同一台服务器上。这样的话,在整个会话期间,用户所有的请求都在同一台服务器上进行处理,即Session绑定在某台特定服务器上,保证Session总能在这台服务器上获取。(这种方案又叫做会话粘滞)。
但是,这种方案不符合高可用的需求。因为一旦某台服务器宕机,那么该机器上得Session也就不复存在了,用户请求切换到其他机器后因为没有Session而无法完成业务处理。因此,很少有网站采用此方案进行Session管理。
③Cookie记录Session:利用浏览器支持的Cookie记录Session简单易行,可用性高,并且支持服务器的线性伸缩,因此,许多网站都或多或少地使用了Cookie来记录Session。但是Cookie记录Session有缺点:比如受Cookie大小限制、每次请求响应都要传输Cookie影响性能、用户关闭了Cookie会造成访问不正常等。
④Session服务器:利用独立部署的Session服务器(集群)统一管理Session,应用服务器每次读写Session时,都访问Session服务器。这种方案实际上是将应用服务器的状态分离,分为无状态的应用服务器和有状态的Session服务器。
从上面的几种方式来看,各有利弊,但Session服务器是最符合高可用需求的方案,也是企业中经常用到的方案。那么,对于有状态的Session服务器,一种较简单的方法是利用分布式缓存(如Memcached、Redis等,有关Redis的简单介绍可以阅读我的博文:NoSQL初探之人人都爱Redis)、数据库等,在这些产品的基础上进行封装,使其符合Session的存储和访问要求。