多tomcat的session

作者 : 开心源码 本文共3082个字,预计阅读时间需要8分钟 发布时间: 2022-05-11 共58人阅读

实现分布式Session所面临的挑战

实现分布式session最大的挑战莫过于如何实现session在分布式系统之间的共享。在分布式环境下,每个子系统都是跨网络的独立JVM,在这些JVM之间实现共享数据的方式无非就是TCP/IP通讯。无论是memcached,还是ZooKeeper,底层都是基于TCP/IP的。所以,我认为用何种工具实现分布式Session都是可行的,没有那种实现优于另外一种实现,在不同的应使用场景,各有优缺点。世间万物,无十全十美,不要盲目的崇拜某种技术,唯有适合才是真理。

Session ID的共享

Session ID是一个实例化Session对象的唯一标识,也是它在Web容器中能被识别的唯一身份标签。Jetty和Tomcat容器会通过一个Hash算法,得到一个唯一的ID字符串,而后赋值给某个实例化的Session,此时,这个Session即可以被放入Web容器的SessionManager中开始它短暂的一生。在Servlet中,我们能通过HttpSession的getId()方法得到这个值,但是我们无法改变这个值。当Session走到它一生尽头的时候,Web容器的SessionManager会根据这个ID将其“火化”。所以Session ID是非常重要的一个属性,并且要保证它的唯一性。在单系统中,Session ID只要要被自身的Web容器读写,但是在分布式环境中,多个Web容器需要共享同一个Session ID。因而,当某个子系统的Web容器产生一个新的ID时,它必需需要一种机制来通知其余子系统,并且告知新ID是什么。

Session中数据的复制

和共享Session ID的问题一样,在分布式环境下,Session中的使用户数据也需要在各个子系统中共享。当使用户通过HttpSession的setAttribute()方法在Session中设置了一个使用户数据时,它只存在于当前与使用户交互的那个Web容器中,而对其余子系统的Web容器来说,这些数据是不可见的。当使用户在下一步跳转到另外一个Web容器时,则又会创立一个新的Session对象,而此Session中并不包含上一步骤使用户设置的数据。其实Session在分布式系统之间的复制实现是简单的,但是每次在Session数据发生变化时,都在子系统之间复制一次数据,会大大降低使用户的响应速度。因而我们需要一种机制,就可以保证Session数据的一致性,又不会降低使用户操作的响应度。

Session的失效

Session是有生命周期的,当Session的空闲时间(maxIdle属性值)超出限制时,Session就失效了,这种设计主要是考虑到了Web容器的可靠性。当一个系统有上万人用时,就会产生上万个Session对象,因为HTTP的无状态特性,服务器无法确切的知道使用户能否真的离开了系统。因而假如没有失效机制,所有被Session占据的内存资源将永远无法被释放,直到系统崩溃为止。在分布式环境下,Session被简单的创立,并且通过某种机制被复制到了其余系统中。你无法保证每个子系统的时钟都是一致的,可可以相差几秒,甚至相差几分钟。当某个Web容器的Session失效时,可可以其余的子系统中的Session并未失效,这时会产生一个有趣的现象,一个使用户在各个子系统之间跳转时,有时会提醒Session超时,而有时又可以正常操作。因而我们需要一种机制,当某个系统的Session失效时,其余所有系统的与之相关联的Session也要同步失效。

类装载问题

在单系统环境下,所有类被装载到“同一个”ClassLoader中。我在同一个上打了引号,由于实际上并非是同一个ClassLoader,只是逻辑上我们认为是同一个。这里涉及到了JVM的类装载机制,因为这个主题不是本文的探讨重点,所以相关介绍能参考相关的JVM文档。因而即便是由memcached或者是ZooKeeper返回的字节数组也能正常的反序列化成相对应的对象类型。但是在分布式环境下,问题就变得异常的复杂。我们通过一个例子来形容这个问题。使用户在某个子系统的Session中设置了一个User类型的对象,通过序列化,将User类型的对象转换成字节数组,并通过网络传输到了memcached或者是ZooKeeper上。此时,使用户跳转到了另外一个子系统上,需要通过getAttribute方法从memcached或者是ZooKeeper上得到先前设置的那个User类型的对象数据。但是问题出现了,在这个子系统的ClassLoader中并没有装载User类型。因而在做反序列化时出现了ClassNotFoundException异常。

实现多tomcat的session共享的思路

1. 通过nginx负载均衡的hash策略,将对应的sessionId分配到对应的tomcat上,但这样并没有实现session共享,本质还是单机的tomcat,一旦这台tomcat宕机,这个session也就失效了。

2. 用户端Cookie保存。用户端Cookie保存以cookie加密的方式保存在用户端.优点是减轻服务器端的压力,每次session信息被写在客服端,而后经浏览器再次提交到服务器。即便两次请求在集群中的两台服务器上完成,也能到达session共享。

3. tomcat自带的集群方式,每台tomcat的session变化就广播给所有的tomcat,这样效率低,很多资源使用于广播和存储session信息上。

4.把Session持久化到数据库。将session持久化到数据中这种共享session的方式即将session信息存入数据库中,其它应使用能从数据库中查出session信息。目前采使用这种方案时所用的数据库一般为mysql。 利使用数据库共享 session 的方案有肯定的实使用性,但也有如下缺点:首先 session 的并发读写在数据库中完成,对 mysql 的性可以要求比较高;其次,我们需要额外地实现 session 淘汰(超时)逻辑代码,即定时从数据库表中升级和删除 session 信息,添加了工作量。

5.利使用memcached实现,memcached存储session,并把多个tomcat的session集中管理,前台在利使用nginx负载均衡和动静态资源分离。

6.利使用redis实现。用redis不仅仅能将缓存的session持久化,还由于它支持的单个对象比较大,而且数据类型丰富,不只是缓存 session,还能做其余使用途,能一举几得。

7.用Zookeeper实现分布式Session,采使用了ZooKeeper集群,ZooKeeper集 群是由一台领导者服务器和若干台跟随者服务器构成(总服务器数要奇数)。所有的读操作由跟随者提供,而写操作由领导者提供,并且领导者还负责将写入的数据 复制到集群中其余的跟随者。当领导者服务器因为故障无法访问时,剩下的所有跟随者服务器就开始进行领导者的选举。通过选举算法,最终由一台本来是跟随者的 服务器更新为领导者。当然原来的领导者服务器一旦被恢复,它就只可以作为跟随者服务器,并在下一次选举中争夺领导者的位置。

Web容器中的Session容器也将发生变化。它不再对使用户的Session进行本地管理,而是委托给ZooKeeper和我们自己实现的Session管理器。也就是说,ZooKeeper负责Session数据的存储,而我们自己实现的Session管理器将负责Session生命周期的管理。

多tomcat的session

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 多tomcat的session

发表回复