Java 多应用服务器Session共享问题

本文探讨了使用Memcached作为分布式系统中的Session管理工具的方法。详细介绍了两种流行的应用方式:一是修改Servlet容器,二是使用过滤器的方式。此外还讨论了如何应对用户数量庞大时的挑战。
1、memcache在一定时间内应该足够大,这样不会出现用户session从Cache中被清除的问题。 
2、如果session的读取比写入要多很多,可以在memcache前再加一个Oscache,减少对memcache的读操作,从而减小网络开销,提高性能(这也是codeutil提出的,我自己也实现了,不过没有加入源码,大家可以自己做)。 
3、如果用户非常多,可以使用memcached组,通过set方法中带hashCode,插入到某个memcached服务器 

其实使用memcached做session管理,我认为是把memcached作为一个可以相对持久化的内存工具

目前大多数大型网站的服务器都采用了分布式的部署方式,但是session是在服务器端保存的,如果用户跳转到其他服务器的话,session就会丢失,于是就有了分布式系统的session共享问题。

session共享有很多解决方法,比较常用的如下:

一、以cookie加密的方式保存在客户端.优点是减轻服务器端的压力,缺点是受到cookie的大小限制,可能占用一定带宽,因为每次请求会在头部附带一定大小的cookie信息,另外这种方式在用户禁止使用cookie的情况下无效.

二、服务器间同步。定时同步各个服务器的session信息,此方法可能有一定延时,用户体验也不是很好。

三、以某种媒介共享session信息,比如memcached,NFS等

本文主要介绍通过memcached共享的方式.

以memcached共享的方式实现的目前比较流行的有两种,一种是修改servlet容器,修改容器代码中的session相关代码,使其连接memcached,在memcached中创建和更新session.目前实现的有tomcat的插件,详见:http://code.google.com/p/memcached-session-manager/,优点是你不用考虑session共享的问题了,可以专注于你的程序开发,向正常使用session那样使用就完事了,缺点是如果你想改变session策略的话,必须重新部署每个服务器的servlet容器.而且修改容器代码存在一定的稳定性风险.如果不小心改坏了,就不爽了,另外如果servlet容器升级,必须做相应修改,也比较麻烦.

另外一种是使用过滤器的方式,可参照网上例子:http://laoer.iteye.com/blog/82565 的例子,此方式使用过滤器的方式重新对httpRequest 对象进行了包装,并加入memcached客户端,此方式的优点是:使用简单,把过滤器配置进去即可,另外比较灵活,因为它是再客户端实现的,配置比较灵活,而且服务器无关,你可以在任何支持servlet的容器上部署。缺点:当然他的缺点也是第一种方式的缺点,受制于memcached,比如:如果出现内存紧张的情况,根据memcached的LRU算法,有可能将用户的一部分session覆盖,从而导致部分session丢失.

笔者根据http://laoer.iteye.com/blog/82565的代码,重新写了一个过滤器,并添加session过期的功能,目前已在struts2中成功应用.详见附件.

### 通过Spring Session实现Java应用间的Session共享 在分布式系统中,多个服务之间共享Session是实现用户状态一致性的重要需求。一种常见且高效的解决方案是使用**Spring Session**,它能够轻松地在多个微服务之间共享Session数据,并支持多种存储后端,如Redis、JDBC等。 #### 配置Spring Session与Redis集成 为了实现在多个Java服务共享Session,可以通过配置Spring Boot项目中的`application.properties`文件来启用Spring Session并将其绑定到Redis服务器[^3]。以下是一个典型的配置示例: ```properties server.port=8077 spring.redis.host=127.0.0.1 spring.redis.port=6379 # spring.redis.password=123456 # 可选:如果Redis设置了密码 server.servlet.session.timeout=30m # 设置Session过期时间,默认为30分钟 server.servlet.session.cookie.path=/ # 设置Cookie路径 server.servlet.session.cookie.domain=myweb.com # 设置Cookie的Domain,用于跨子域名共享Session ``` 上述配置启用了基于Redis的Session管理机制,其中`spring.redis.host`和`spring.redis.port`指定了Redis服务器的位置,而`server.servlet.session.timeout`定义了Session的有效期。此外,通过设置`server.servlet.session.cookie.domain`,可以在多个子域名下共享同一个Session标识(jsessionid),从而避免服务之间的Session混淆。 #### 使用Redis作为Session存储的优势 Spring Session结合Redis提供了一种高性能、可扩展的Session共享方案。Redis以其低延迟、高吞吐量以及持久化能力,非常适合用作Session数据的临时存储介质。通过将Session信息存入Redis,所有接入该Redis的服务都可以访问相同的Session数据,确保了用户状态在整个分布式系统中的一致性[^2]。 #### 上下文隔离与Session共享的兼容性处理 对于部署在同一容器下的多个Web应用(例如TongWeb),可以通过获取其他应用的上下文对象来访问其Session信息。具体来说,一个应用B可以使用如下代码来获取另一个应用A的上下文,并从中读取或写入Session数据: ```java ServletContext aContext = req.getSession().getServletContext().getContext("/A"); HttpSession sessionInA = (HttpSession) aContext.getAttribute("sessionAttributeName"); ``` 这种方式允许应用间共享特定的Session属性,但需要注意的是,直接操作其他应用的Session可能会引入耦合性和安全性问题,因此建议仅用于必要的场景,并做好权限控制。 #### Cookie路径与域的设置 为了避免服务间的`jsessionid`冲突,需要合理设置Session Cookie的路径(Path)和域(Domain)。通过统一设置`server.servlet.session.cookie.domain`为共同的父域名(如`.myweb.com`),可以让浏览器在访问同一域下的同子服务时携带相同的Session ID,从而实现跨服务Session共享。同时,设置`server.servlet.session.cookie.path`为`/`可以保证整个站点范围内的Cookie可用性。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值