session转移处理:
1,cas可以不考虑session转移,转移到那个服务就临时生成session
http://blog.csdn.net/matthewei6/article/details/50682939
2,用tomcat服务器实时同步复制(配置)
http://blog.csdn.net/woaigaolaoshi/article/details/50902010(几种方法)
3,zk,redis ,memcahe
使用备份存3储思想的时候,需要自己java代码做过滤器,监听
准备知识:
getsession().getId() 与 getRequestSessionId()的区别
HttpServletRequest.getSession().getId()是服务器端的概念,如果没有你这个客户端的session会新建一个对应当前request
HttpServletRequest.getRequestedSessionId()是客户端就是浏览器的概念。
cookie就是sessionid,避免每次都跟在url后面
HTTP连接是无状态的,那么如何维护一个Session呢?其实就是通过这个HttpServletRequest.getRequestedSessionId(),
如果大家细心一些,有时候会发现有时候浏览器的地址栏或者状态栏里面的地址后面会带一个sessionId的参数值,
这就是HttpServletRequest.getRequestedSessionId()的返回值。而且这个值一般也会存在cookie里面,
这样就避免了在每次请求的时候都带在请求的URL里面或者FORM里面,它是随着浏览器和服务器端的Cookie进行交流,对于用户和开发人员是透明的
memcache的备份实现session转移:
1,通过getsession().getId() 与 getRequestSessionId()判断是否转移(一致说明不转移)
2,转移的时候把当前服务器的sessio及里面的用户数据备份更新加上转移过来的
3,同时监听session的增删,和属性的改变随时修改备份
4,用的时候直接用备份
getsession().getId()创建空的后我们用复制过来的session覆盖,这样服务器的新session就是我们以前的session
getsession().getId()创建空的后我们用复制过来的session覆盖,这样服务器的新session就是我们以前的session
用了类似这中第三方的存储介质,都是介质同步服务端的(创建,消除),介质之间监听变化同步(创建,消除,修改I属性),之后web直接从介质中拿,
至于服务端怎么从介质同步,可以getsession().getId()空值的时候服务端自动创建一个session,然后再覆盖这个为当前介质拿的这个,或者直接copy到服务器,
注意这里代码示例,需要将介质中的缓存sesion写入服务器,否则再次请求使用getsession().getId()和HttpServletRequest.getSession().getId()还是不会相等(要不要同步到服务器看你代码的逻辑,没有绕过客户sid和服务sid校验的,要写回服务器),如果你的代码中有复写源码只用客户sid和缓存比较一致这样就不需要回写sessoin到服务端
(当然客户端的cookie也可以用java代码修改)
这个代码示例才叫转移(先用介质存,之后用的时候服务端没有从介质同步过去服务端,再比较客户sid和服务sidgetsession().getId() 与 getRequestSessionId()),后面
一遍代码采用复写直接用缓存的比对,所以用共享的方式处理了session问题,不是用转移的方式
=====================================
最近自己尝试着在linux下面进行开发和学习,想想即使对于一般的企业应用,做一个小的集群也是有必要的,能防止单服务器down掉之后的尴尬,所以就在学习nginx+tomcat配置一个小型的集群,google之下也算搞定,然后自然涉及到session共享之类的问题,依旧想google之,前人经验后人乘凉,搜索后发现最多的文章的解决方式就是开启tomcat的session复制,还有比较多的情况是使用memcached session manager 这个开源框架,这样就能在某个tomcat故障时候防止用户会话失效,这两者都要对tomcat配置文件什么的进行一些不大不小的改动,而且在我尝试之后发现,开启tomcat session复制尤其不可取,尤其在session中内容比较多的情况下(当然,session中放太多东西本身就不应该..),效率很是问题,也有人说在nginx下用iphash,将同一ip会话粘在同一个tomcat服务器上,但是如果在这台tomcat服务器down掉的情况下,却没有给出一个比较好的会话转移解决方法。(或者我没搜到?)
额。前面罗嗦一通是前提,我的一个程序中的解决方法,不必像开启tomcat的session复制或者像memcached session mamager这样对tomcat的配置文件进行修改,只需要代码实现即可。 想法如下:
用memcached 存储用户信息,将会话的sessionId作为key,放了一个map用来存储信息,
这样在会话中如果所粘合的tomcat down掉,nginx将此次会话转发给其他服务器时候,将存储在memcached中的信息复制回来即可。像下面这样:
request--sessionFilter(会话转移filter)--powerFilter(权限验证filter)--action--
首先我在登录的时候做了如下操作:初始化信息
- SessionCacheService.initSessionCache(sessionId,map);
因为采取iphash策略,用户会话是粘合在同一服务器上的,那么当这台服务器down掉后的处理:
用request.getRequestedSessionId();获取上一会话的sessionId去memcached中找,找到后将信息复制到此会话中.
- /**
- * Created by IntelliJ IDEA.
- * User: bjslogin[at]gmail.com
- * Date: 11-8-2
- * Time: 上午10:28
- * 设置nginx为iphash,如果发生故障转移,即会将session信息转移至新的服务器
- */
- public class SessionFilter implements Filter {
- private Logger logger = Logger.getLogger(getClass());
- public void init(FilterConfig filterConfig) throws ServletException {
- }
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- HttpServletRequest request = (HttpServletRequest)servletRequest;
- String url = request.getRequestURI();
- for(String c : PowerFilter.noFilterPages){
- if(url.indexOf(c) > 0){
- filterChain.doFilter(servletRequest,servletResponse);
- return;
- }
- }
- String requestedSessionId = request.getRequestedSessionId();
- HttpSession session = request.getSession();
- if(requestedSessionId.equals(session.getId())){
- filterChain.doFilter(servletRequest,servletResponse);
- return;
- }
- Map<String,Object> _map = SessionCacheService.getSessionCache(session.getId());
- if(_map == null){
- Map<String,Object> map = SessionCacheService.getSessionCache(requestedSessionId);
- if(map == null){
- filterChain.doFilter(servletRequest,servletResponse);
- return;
- }
- logger.info("开始转移...");
- SessionCacheService.initSessionCache(session.getId(),map);
- }
- filterChain.doFilter(servletRequest,servletResponse);
- }
- public void destroy() {
- }
- }
然后我的powerFilter 权限验证filter如下:
- /**
- * Created by IntelliJ IDEA.
- * User: bjslogin[at]gmail.com
- * Date: 11-8-1
- * Time: 下午2:23
- * 权限验证filter
- */
- public class PowerFilter implements Filter {
- private Logger logger = Logger.getLogger(getClass());
- private FilterConfig filterConfig;
- private ApplicationContext ctx = null;
- protected static final String sessionErrorPage = "/sessionError.jsp";
- protected static final String noPermissionPage = "/noPermission.jsp";
- protected static final String[] noFilterPages = {"login.action","logout.action"};
- public void init(FilterConfig filterConfig) throws ServletException {
- this.filterConfig = filterConfig;
- }
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- HttpServletRequest request = (HttpServletRequest)servletRequest;
- String url = request.getRequestURI();
- logger.info("【"+request.getRemoteHost()+"[at]"+new Date()+"】"+url);
- for(String c : noFilterPages){
- if(url.indexOf(c) > 0){
- filterChain.doFilter(servletRequest,servletResponse);
- return;
- }
- }
- HttpSession session = request.getSession();
- Map<String,Object> map = SessionCacheService.getAndRefreshSessionCache(session.getId());
- if(map == null){
- HttpServletResponse response = (HttpServletResponse)servletResponse;
- response.sendRedirect(request.getContextPath() + sessionErrorPage);
- return;
- }
- LoginService loginService = (LoginService)getBean(LoginService.class);
- boolean flag = loginService.checkPrivate(request.getSession().getId(),StringUtils.substringAfter(url,request.getContextPath() + "/"));
- if(!flag){
- HttpServletResponse response = (HttpServletResponse)servletResponse;
- response.sendRedirect(request.getContextPath() + noPermissionPage);
- return;
- }
- filterChain.doFilter(servletRequest,servletResponse);
- }
- public void destroy() {
- }
- public Object getBean(Class clazz) {
- if (ctx == null) {
- ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext());
- }
- return ctx.getBean(clazz);
- }
- }
看的出来我是用cache里面的信息来判断会话失效的,放弃使用HttpSession了,只用了它的ID,当然,这只是我的个人做法,要使用session存储信息的话,就是类似于将将memcached作为一个session信息的备份了,添加两个listener保证session和memcached同步即可,我的做法:
- /**
- * Created by IntelliJ IDEA.
- * User: bjslogin[at]gmail.com
- * Date: 11-8-1
- * Time: 上午11:07
- * session失效时同时干掉缓存
- */
- public class SessionCacheListener implements HttpSessionListener{
- public void sessionCreated(HttpSessionEvent httpSessionEvent) {
- // do nothing
- // 登陆时才初始化sessionCache内容
- }
- //session失效时同时移除缓存内容
- public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
- HttpSession session = httpSessionEvent.getSession();
- SessionCacheService.removeSessionCache(session.getId());
- }
- }
这个是监听session属性变化的listener,保证当session内容变化时候能同步到cache中
- /**
- * Created by IntelliJ IDEA.
- * User: bjslogin[at]gmail.com
- * Date: 11-8-1
- * Time: 上午11:28
- * 监听session属性变化,同步cache
- */
- public class SessionCacheAttributeListener implements HttpSessionAttributeListener {
- public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
- HttpSession session = httpSessionBindingEvent.getSession();
- String key = httpSessionBindingEvent.getName();
- Object value = httpSessionBindingEvent.getValue();
- SessionCacheService.putSessionCacheAttribute(session.getId(), key, value);
- }
- public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
- HttpSession session = httpSessionBindingEvent.getSession();
- String key = httpSessionBindingEvent.getName();
- SessionCacheService.removeSessionCacheAttribute(session.getId(), key);
- }
- public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
- attributeAdded(httpSessionBindingEvent);
- }
- }
,
这样就能保证session与cache内容同步了,只需要在SessionFilter的SessionCacheService.initSessionCache(session.getId(),map);方法之前将cache中的内copy到session中即可,下一步的powerFIlter判断用户信息就不会出现问题。
在我本机nginx+3个tomcat测试中,将正在被访问的tomcat人为down掉,确实是能保证会话平滑转移的,我的nginx的集群配置方式:
- upstream localhost {
- ip_hash;
- server localhost:8060;
- server localhost:8070;
- server localhost:8080;
- }
- server {
- listen 8090;
- server_name localhost;
- location / {
- proxy_connect_timeout 3;
- proxy_send_timeout 30;
- proxy_read_timeout 30;
- proxy_pass http://localhost;
- }
- }
- }
不过据我所知,如果客户端禁用cookie的话,request.getRequestedSessionId()可能就有问题了,,不过。。不管啦!
这是我的一个解决方法,贴出来与大家分享。觉得这么做最大的好处就是和服务器无关,像session复制和memcached session manager这样都是依赖tomcat服务器。
毕业一年,还只是新手,这也是我在iteye的第一贴。。如果这么做有什么错误的话,请指正,我会虚心学习,请言论不要过激。。谢谢。
还有,看了精华贴 【晒晒大家年龄和近期愿望吧】 心中真是感慨万千,感觉天朝上学的时间真是太长了,刚毕业没多久,就觉得时间已经不够用。同时祝帖子里面的朋友愿望都能实现(话说最多的愿望是找个女朋友?)!
相关推荐
在PHP开发中,Session管理是不可或缺的一部分,尤其是在大型分布式系统中。传统的session存储方式,如文件或数据库,可能...在实际应用中,还可以结合负载均衡器、故障转移策略等进一步优化session的可用性和可靠性。
- `SessionTransfer.aspx.cs` 是ASP.NET页面的C#后台代码,可能包含了处理Session转移的逻辑。 - `ASPSessionState.sql` 可能是一个SQL脚本,用于创建存储Session数据的数据库表。 - `Install.txt` 应该包含安装或...
从Session转移到Redis”,意味着开发者正在使用C#语言和Visual Studio(VS)开发环境,研究如何配置和使用Redis来替代ASP.NET中的Session。这是一个常见的做法,因为C#社区提供了丰富的Redis客户端库,如...
此外,为了确保session数据的安全性和一致性,Tomcat-Redis-Session-Manager提供了多种策略,如session过期策略、session复制和故障转移。例如,可以设置session的超时时间,当用户长时间无操作时,session将在Redis...
缺点:缺乏容错性,如果当前访问的服务器发生故障,用户被转移到第二个服务器上时,他的 Session 信息都将失效。 实现方式:可以使用 Nginx 的 upstream 模块配置 ip_hash 属性来实现粘性 Session。 第二种:服务器...
- Session迁移:当用户从一台服务器切换到另一台服务器时,保证Session数据的无缝转移。 - 安全性:加密Session数据,防止数据泄露。 - 超时管理:自动处理过期的Session。 在实际开发中,选择适合的Session共享库...
7. **故障转移和监控**:在高可用集群中,要确保当某个服务器出现问题时,能自动将流量切换到其他健康服务器,同时通过监控工具持续检查系统性能和Session管理的有效性。 通过以上步骤和策略,我们可以构建出一个...
在实际开发中,通常会结合使用Cookie和SESSION来优化购物车体验,例如,可以使用Cookie来临时存储用户未登录时的购物车,当用户登录后,再将Cookie中的购物车数据转移到与用户账户关联的SESSION中。 综上所述,...
7. **故障转移和一致性**:由于memcached是无状态的,所以当某个节点失败时,需要确保Session数据能够自动转移到其他节点,保持会话的一致性。 总之,"Tomcat memcached Session依赖jar包"涉及到的是在Tomcat中使用...
Spring Session提供了一种简单的方法,将Session数据从服务器内存转移到外部存储,比如Redis。在`pom.xml`中添加依赖,然后配置`application.properties`,指定Redis服务器地址、端口和密钥前缀。 ```properties ...
4. **故障转移**: 如果主服务器出现故障,其他服务器已经拥有Session的完整副本,可以无缝接管,保证服务的连续性。 **三、不能进行Session复制的原因** 1. **配置问题**: 集群配置不正确,例如没有启用Session...
8. **故障转移**:在集群环境中,如果某个Tomcat节点宕机,其他节点能够继续提供服务,session的处理也应能平滑过渡,确保用户体验不受影响。 总的来说,实现Tomcat集群session共享是提高系统可用性和一致性的重要...
但在集群中,每个服务器都有自己的内存空间,如果不进行特殊处理,不同服务器无法访问彼此的Session。 3. **Redis介绍**:Redis是一个高性能的键值存储系统,常被用作数据库、缓存和消息代理。它的特点是速度快,...
这样做的好处在于,session数据可以被多个应用服务器共享,实现了session的分布式管理,有效解决了高并发场景下的session处理问题。1.8.1版作为MSM的一个稳定版本,提供了一系列优化和改进,增强了其性能和可靠性。 ...
4. **处理一致性问题**: 如果多个服务器同时修改同一个Session,需要考虑并发一致性问题,如使用分布式锁或者乐观锁来解决。 **使用源码和工具** 标签中的“源码”可能是指需要查看和理解与Redis交互的代码,以及...
"工具"标签则表明`memcached-session-manager`是一个实用工具,用于在Java Web应用中处理session的持久化和分布式存储,可能是通过提供API或者配置选项来实现。 **文件名解析:** "tomcat7"可能是教程中涉及的一个...
- **InProc模式**:不适合大规模应用,因为它不支持群集处理,每个节点上的Session数据都是独立的。 - **StateServer和SQLServer模式**:支持多节点集群,能够较好地支持大规模应用的需求。 #### 结论 选择合适的...
- **Session监听器**:如果你的应用程序使用了自定义session处理逻辑,可能需要添加一个监听器来处理session在集群间的转移。通过实现`javax.servlet.http.HttpSessionListener`接口,你可以监控session的创建和...
6. **容错与故障转移**:由于 Memcached 是分布式系统,如果一个节点失效,memcached-session-manager 可以自动切换到其他可用节点,提供了一定程度的容错能力。 7. **扩展性**:随着Web应用规模的扩大,只需添加更...
在集群模式下,Redis可以提供数据的自动分片、故障转移和高可用性,非常适合处理像Session这样需要全局一致性的数据。 压缩包子文件的文件名称列表揭示了所涉及的库: 1. jedis-2.6.2.jar:这是Java操作Redis的...