一、提出问题:
为了满足足够大的应用,满足更多的客户,于是我们架设了N台Web服务器(N>=2),在多台Web服务器的情况下,我们会涉及到一个问题:用户登陆一台服务器以后,如果在跨越到另一台服务器的时候能够继续使用客户的Session?
二、解决方案:
1. 写客户端Cookie的方式
当用户登陆成功以后,把网站域名、用户名、密码、token、 session有效时间全部采用cookie的形式写入到客户端的cookie里面,如果用户从一台Web服务器跨越到另一台服务器的时候,我们的程序主动去检测客户端的cookie信息,进行判断,然后提供对应的服务,当然,如果cookie过期,或者无效,自然就不让用户继续服务了。当然,这种方法的弊端就不言而喻了,比如客户端禁用了cookie或者cookie被黑客窃取了呢?这些都可以解决,目前淘宝session框架就是基于client cookie做开发,不见得他们就出了很大的问题?也许是最可行的方式,可以配合memcached来实现。
2. 服务器之间Session数据同步的方式
假设Web服务器A是所有用户登陆的服务器,那么当用户验证登陆一下,session数据就会写到A服务器里,那么就可以自己写脚本或者守护进程来自动把session数据同步到其他Web服务器,那么当用户跳转到其他服务器的时候,那么session数据是一致的,自然就能够直接进行服务无须再次登陆了。缺点是,可能会速度慢,不稳定,如果是单向同步的话,登陆服务器出现问题,那么其他服务器也无法服务,当然也可以考虑双向同步的问题。这个方案都可以解决,目前zookeeper可以实现。
3. 利用NFS共享Session数据的方式
其实这个方案和下面的Mysql方案类似,只是存储方式不一 样。大致就是有一台公共的NFS服务器(Network File Server)做共享服务器,所有的Web服务器登陆的时候把session数据写到这台服务器上,那么所有的session数据其实都是保存在这台 NFS服务器上的,不论用户访问哪台Web服务器,都要来这台服务器获取session数据,那么就能够实现共享session数据了。缺点是依赖性太强,如果NFS服务器down掉了,那么大家都无法工作了,当然,可以考虑多台NFS服务器同步的形式。这个方案都可以解决,目前zookeeper可以实现,当然memcached也可以实现session共享。
4. 利用Mysql数据库共享Session数据的方式
这个方式与NFS的方式类似,也是采用一台Mysql服务器做共享服务器,把所有的session的数据保存到Mysql服务器上,所有Web服务器都来这台Mysql服务器来获取Session 数据。缺点也是依赖性太强,Mysql无法工作了影响所有的Web服务器,当然,可以考虑多太Mysql数据库来共享session,使用同步Mysql 数据的方式。这种方式跟方式3类似,同样可以采用memcached来做,nosql也可以实现,这些都不是问题。
5. 使用硬件设备
这个算是比较成熟的解决方案了,使用类似BIG-IP的负载设备来实现资源共享,那么就能够又稳定又合理的的共享Session了。目前很多门户网站采用这种方式。缺点很明显了,就是要收费了,硬件设备肯定需要购买成本的,不过对于专业或者大型应用来讲,是比较合理并且值得的,这种方式可以放到最后面考虑。
为了满足足够大的应用,满足更多的客户,于是我们架设了N台Web服务器(N>=2),在多台Web服务器的情况下,我们会涉及到一个问题:用户登陆一台服务器以后,如果在跨越到另一台服务器的时候能够继续使用客户的Session?
二、解决方案:
1. 写客户端Cookie的方式
当用户登陆成功以后,把网站域名、用户名、密码、token、 session有效时间全部采用cookie的形式写入到客户端的cookie里面,如果用户从一台Web服务器跨越到另一台服务器的时候,我们的程序主动去检测客户端的cookie信息,进行判断,然后提供对应的服务,当然,如果cookie过期,或者无效,自然就不让用户继续服务了。当然,这种方法的弊端就不言而喻了,比如客户端禁用了cookie或者cookie被黑客窃取了呢?这些都可以解决,目前淘宝session框架就是基于client cookie做开发,不见得他们就出了很大的问题?也许是最可行的方式,可以配合memcached来实现。
2. 服务器之间Session数据同步的方式
假设Web服务器A是所有用户登陆的服务器,那么当用户验证登陆一下,session数据就会写到A服务器里,那么就可以自己写脚本或者守护进程来自动把session数据同步到其他Web服务器,那么当用户跳转到其他服务器的时候,那么session数据是一致的,自然就能够直接进行服务无须再次登陆了。缺点是,可能会速度慢,不稳定,如果是单向同步的话,登陆服务器出现问题,那么其他服务器也无法服务,当然也可以考虑双向同步的问题。这个方案都可以解决,目前zookeeper可以实现。
3. 利用NFS共享Session数据的方式
其实这个方案和下面的Mysql方案类似,只是存储方式不一 样。大致就是有一台公共的NFS服务器(Network File Server)做共享服务器,所有的Web服务器登陆的时候把session数据写到这台服务器上,那么所有的session数据其实都是保存在这台 NFS服务器上的,不论用户访问哪台Web服务器,都要来这台服务器获取session数据,那么就能够实现共享session数据了。缺点是依赖性太强,如果NFS服务器down掉了,那么大家都无法工作了,当然,可以考虑多台NFS服务器同步的形式。这个方案都可以解决,目前zookeeper可以实现,当然memcached也可以实现session共享。
4. 利用Mysql数据库共享Session数据的方式
这个方式与NFS的方式类似,也是采用一台Mysql服务器做共享服务器,把所有的session的数据保存到Mysql服务器上,所有Web服务器都来这台Mysql服务器来获取Session 数据。缺点也是依赖性太强,Mysql无法工作了影响所有的Web服务器,当然,可以考虑多太Mysql数据库来共享session,使用同步Mysql 数据的方式。这种方式跟方式3类似,同样可以采用memcached来做,nosql也可以实现,这些都不是问题。
5. 使用硬件设备
这个算是比较成熟的解决方案了,使用类似BIG-IP的负载设备来实现资源共享,那么就能够又稳定又合理的的共享Session了。目前很多门户网站采用这种方式。缺点很明显了,就是要收费了,硬件设备肯定需要购买成本的,不过对于专业或者大型应用来讲,是比较合理并且值得的,这种方式可以放到最后面考虑。
(1)简单架构
Tomcat下多项目Session共享
![](http://dl2.iteye.com/upload/attachment/0111/1131/e147ffb1-0899-3f72-8773-4bc862dbbcb0.png)
(2)功能简述
![](http://dl2.iteye.com/upload/attachment/0111/1133/1787a265-4e96-3439-aeb2-be242b5cc5b0.png)
![](http://dl2.iteye.com/upload/attachment/0111/1135/79fea311-eeea-306f-8346-3be845289588.png)
(3)代码简介,目前实现的很简单,后续会扩展
(3.1)统一拦截器模式
package com.crm.interceptor; import java.util.List; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import com.crm.application.CrmApplication; import com.crm.exception.SessionTimeoutException; import com.crm.model.operator.BOCrmOperator; public class CrmInterceptor implements HandlerInterceptor { private static Log log = LogFactory.getLog(CrmInterceptor.class); @Autowired private CrmApplication CrmApplication; private List<String> allowUrls; public void setAllowUrls(List<String> allowUrls) { this.allowUrls = allowUrls; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { log.info("==============执行顺序: 1.preHandle================"); String requestURI = request.getRequestURI(); for (String allowUrl : allowUrls) { if (requestURI.endsWith(allowUrl)) { return true; } } String crmSessionValue = ""; Cookie[] allCookies = request.getCookies(); if (allCookies != null) { for (int i = 0; i < allCookies.length; i++) { if (allCookies[i].getName().equals(CrmApplication.crmSessionId)) { crmSessionValue = allCookies[i].getValue(); break; } } } //1.检测用户cookie中是否包含自定义的sessionId //2.取值的时候 //(2.1)内存取值 //(2.2)Http请求取值 //(2.3)Redis取值 //(2.4)memcached取值 BOCrmOperator o = CrmApplication.getCrmSessionMap(crmSessionValue); System.out.println(o); Object sessionOperator = request.getSession().getAttribute("sessionOperator"); if (sessionOperator != null) { return true; } else { throw new SessionTimeoutException("用户未登录/用户状态时效,需要重新登陆"); } } public String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } @Override // 在业务处理器处理请求执行完成后,生成视图之前执行的动作 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView mv) throws Exception { String s = request.getServletPath(); String c = request.getContextPath(); String uri = request.getRequestURI(); String url = request.getRequestURL().toString(); StringBuffer path = new StringBuffer("http://"); path.append(request.getServerName()); path.append(":"); path.append(request.getServerPort()); path.append(request.getContextPath()); if (mv != null) { mv.addObject("path", path.toString()); } log.info(response); log.info("==============执行顺序: 2.postHandle================"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3) throws Exception { // log.info("==============执行顺序: 3.afterCompletion================"); } }
(3.2)认证模块
@RequestMapping(value = { "/" }, method = RequestMethod.GET) public String init(HttpServletRequest req, HttpServletResponse res, Model m) { BOCrmOperator o = (BOCrmOperator) req.getSession().getAttribute("sessionOperator"); List<BOCity> operatorCityList = OperatorCityRelSVImpl.getOperatorCitys(o.getId()); m.addAttribute("operatorCityList", operatorCityList); m.addAttribute("sessionCity", operatorCityList.get(0)); String crmSessionValue = UUID.randomUUID().toString().replace("-", ""); CrmApplication.setCrmSessionMap(crmSessionValue, o); Cookie myCookie = new Cookie(CrmApplication.crmSessionId, crmSessionValue); myCookie.setMaxAge(60000); myCookie.setPath("/"); res.addCookie(myCookie); return "index/index"; }
(3.3)获取用户信息
public static Operator getOperatorInSession(HttpServletRequest request) { Operator o = null; String crmSessionValue = ""; Cookie[] allCookies = request.getCookies(); if (allCookies != null) { for (int i = 0; i < allCookies.length; i++) { if (allCookies[i].getName().equals("crmSessionId")) { crmSessionValue = allCookies[i].getValue(); break; } } } if ("".equals(crmSessionValue)) { System.out.println("用户未登录"); } else { String json = HttpUtil .sendGet("http://localhost:8080/crm/authOperator?crmSessionId=" + crmSessionValue); System.out.println(json); o = GsonUtil.getGson().fromJson(json, Operator.class); } return o; }
相关推荐
描述中提到的“nginx+tomcat8+memcached session共享所需jar包,直接放到tomcat/lib下即可”,暗示了实现这一功能需要一些特定的Java库(JAR包)。这些JAR包将集成到Tomcat的运行环境中,使Tomcat能够与Memcached...
这个小例子"nginx+tomcat+redis完成session共享"旨在演示如何通过这三种技术实现跨服务器的用户会话共享,以提升用户体验并简化系统管理。以下是这些技术及其在会话共享中的作用: 1. **Nginx**:Nginx是一款高性能...
在这个场景中,我们关注的是如何在Tomcat集群环境中实现Session共享,以便提高应用程序的可扩展性和可用性。标题和描述提到的“session共享包”是解决这一问题的关键。 **什么是Session?** 在Web应用中,Session是...
标题中的“nginx实现多个tomcat7直接session共享所需jar包”指的是在分布式系统环境中,使用Nginx作为反向代理服务器,将用户请求分发到多个Tomcat7应用服务器上,同时实现用户会话(Session)在这些服务器之间的...
当我们谈论“Tomcat7集群实现session共享”时,我们关注的是如何在多个Tomcat实例之间有效地同步用户会话信息,以便在集群环境中提供高可用性和负载均衡。 首先,理解session共享的重要性。在Web应用中,session是...
总结来说,"nginx+tomcat shiro实现多tomcat下session共享"是一种常见的分布式系统架构策略,通过Nginx的负载均衡、Shiro的会话管理以及Redis的中央存储,有效地解决了多服务器环境下session共享的问题,提高了系统...
在分布式系统中,Session共享是一个常见的需求,尤其是在使用Tomcat这样的Servlet容器时。"tomcat-redis-session-manager"是一个解决方案,它将用户的Session信息存储在Redis缓存服务器中,从而实现跨服务器的...
1. **创建测试页面**:在两个Tomcat的`webapps/ROOT`目录下创建一个简单的JSP页面`test.jsp`,用于测试Session共享。 2. **启动服务**:确保两个Tomcat、Redis和Nginx都已经启动。 3. **访问页面**:在浏览器中访问`...
通过以上步骤,我们成功地实现了基于Tomcat7和Redis的Session共享,确保了在Nginx负载均衡下的应用能够无缝处理用户的会话状态。这种方式不仅可以解决Session丢失的问题,还具有高可用性,因为Redis可以提供持久化...
在单个服务器上,Session可以通过内存来管理,但在分布式环境下,多个服务器无法共享同一个内存中的Session,这就需要引入外部存储来实现Session共享。 Redis是一个高性能的键值数据库,常被用作缓存和会话存储解决...
`tomcat-redis-session-manager`就是这样一款解决方案,它将Tomcat的session管理与Redis相结合,实现了跨服务器的session共享。 首先,让我们理解`tomcat-redis-session-manager`的核心概念。这是一个开源项目,它...
这里提到的"session 共享 tomcat-redis-session-manager"就是一种解决方案,它利用Redis作为中央存储来实现Tomcat容器中的Session共享。 首先,我们来看看标题所提及的"session 共享 tomcat-redis-session-manager...
在分布式系统中,Session共享是一个常见的需求,尤其是在多个Tomcat实例组成的集群中。为了实现这样的功能,我们可以利用Redis作为中间缓存服务器,存储和管理用户的Session数据。下面将详细介绍如何配置Tomcat与...
tomcat8.5.29 redisclouder集群 session共享集群相关配置文件 亲测可用tomcat8.5.29 redisclouder集群 session共享集群相关配置文件 亲测可用 tomcat8.5.29 redisclouder集群 session共享集群相关配置文件 亲测可用 ...
tomcat8 redis session共享,提供commons-pool2-2.3.jar,jedis-2.7.2.jar和修改后的tomcat-redis-session-manager-master-2.0.0.jar及部署文档
tomcat8 Redis集群 同步Session 中用到的jar 附带tomcat content.xml配置文件
基于之前支持Tomcat7以下的redis-Session共享机制 进行相关适配的修改打包,里面包含所需Jar包以及相关的说明配置文档,包括:--单点授权Reids配置;- Sentinel 配置 ;- Redis Cluster 配置 ;适用于Tomcat8的容器环境...
通过这种方式,"tomcat7+redis集群 session共享jar"可以帮助开发者解决在Tomcat7集群中Session共享的问题,提升系统的可扩展性和可用性。在大型网站和分布式应用中,这样的解决方案能够保证用户在不同服务器之间切换...
描述中的"下载后直接复制粘贴到Tomcat的lib里面就行了,配置的话自己可以看下教程"暗示了这个压缩包包含了一些必要的JAR文件,这些文件是集成Redis和Tomcat以实现Session共享所需的库。用户只需将这些文件放入Tomcat...
Tomcat二级域名Session共享例子,具体操作看博客:http://blog.csdn.net/luogqing/article/details/78595200