现在集群中使用的Session共享机制有两种,分别是session复制和session粘性。
- Session复制
该种方式下,负载均衡器会根据各个node的状态,把每个request进行分发,使用这样的测试,必须在多个node之间复制用户的session,实时保持整个集群中用户的状态同步。其中jboss的实现原理是使用拦截器,根据用户的同步策略拦截request,做完同步处理后再交给server产生响应。
优点:session不会被绑定到具体的node,只要有一个node存活,用户状态就不会丢失,集群能够正常工作。
缺点:node之间通信频繁,响应速度有影响,高并发情况下性能下降比较厉害。
- Session粘性
该种方式下,当用户发出第一个request后,负载均衡器动态的把该用户分配至到某个节点,并记录该节点的jvm路由,以后该用户的所有的request都会绑定到这个jvm路由,用户只会和该server交互。
优点:响应速度快,多个节点之间无需通信
缺点:某个node死掉之后,它负责的所有用户都会丢失session。
改进:servlet容器在新建、更新或维护session时,向其它no de推送修改信息。这种方式在高并发情况下同样会影响效率。
以上这两种方式都需要负载均衡器和Servlet容器的支持,在部署时需要单独配置负载均衡器和Servelt容器。
- 基于分布式缓存的session共享机制
将会话Session统一存储在分布式缓存中,并使用Cookie保持客户端和服务端的联系,每一次会话开始就生成一个GUID作为SessionID,保存在客户端的Cookie中,在服务端通过SessionID向分布式缓存中获取session。
实现思路:通过一个Filter过滤所有的request请求,在Filter创建request和session的代理,通过代理使用分布式缓存对session进行操作。这样实现对现有应用中对request对象的操作透明。
- 使用spring实现:
引入spring-session和redis依赖:
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency>
1.创建redis连接工厂
public class RedisConfig { private String host = null ; private Integer port = null ; /** * redis连接工厂 * @return */ @Bean public JedisConnectionFactory connectionFactory(Environment environment){ //获取redis主机和port this.host = environment.getRequiredProperty("redis.host") ; //默认端口号为6379 this.port = environment.getProperty("redis.port", Integer.class, 6379) ; JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory() ; jedisConnectionFactory.setHostName(host); jedisConnectionFactory.setPort(port); JedisPoolConfig jedisPoolConfig = new JedisPoolConfig() ; jedisPoolConfig.setMinIdle(1); jedisPoolConfig.setMaxTotal(10); //最长等待10s jedisPoolConfig.setMaxWaitMillis(10000); jedisPoolConfig.setTestOnBorrow(true); jedisConnectionFactory.setPoolConfig(jedisPoolConfig); return jedisConnectionFactory ; } @Bean public StringRedisTemplate redisTemplate(RedisConnectionFactory connectionFactory){ StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(connectionFactory) ; return stringRedisTemplate ; } }
2.引入RedisHttpSessionConfiguration.class。通过java-config引入或在xml中引入,因为要实现零XML配置,所以使用java-config引入。
/** *基于redis的session共享配置 */ @EnableRedisHttpSession(maxInactiveIntervalInSeconds=Constants.SESSION_TIMEOUT) public class SessionRedisConfig { }
3.创建HttpSessionApplicationInitializer,继承AbstractHttpSessionApplicationInitializer,HttpSessionApplicationInitializer不需要重载或实现任何方法,这个类只是一个使用Redis存储Session的一个标示类。在Servlet容器初始化时,会通过编码的方式添加一个Filter,通过WebApplicationContext查找名为springSessionRepositoryFilter的Filter类对request、response和session进行包装。
AbstractHttpSessionApplicationInitializer实现了WebApplicationInitializer接口。在Servlet3.0规范中,会自动扫描配置的ServletContainerInitializer的实现类,在实现类中可以配置需要处理的类。如下是SpringServletContainerInitializer,在启动时会自动寻找所有的WebApplicationInitializer实现类。
@HandlesTypes(WebApplicationInitializer.class) public class SpringServletContainerInitializer implements ServletContainerInitializer { ...... }
关于Servlet3.0规范,参考附件Servlet3.1规范(最终版)。
说明:
- @EnableRedisHttpSession引入了RedisHttpSessionConfiguration.class,主要进行了如下配置:
//获取EnableRedisHttpSession中maxInactiveIntervalInSeconds,即session检测的最大时间间隔 public void setImportMetadata(AnnotationMetadata importMetadata){} //通过spring容器中的connectionFactory创建RedisTemplate public RedisTemplate<String,ExpiringSession> sessionRedisTemplate(RedisConnectionFactory connectionFactory) {} //创建对session操作的工厂 public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, ExpiringSession> sessionRedisTemplate) {} //创建filter,真正包装request、response和session对象的类。其中httpSessionStrategy默认使用的是CookieHttpSessionStrategy,即将session ID存储在cookie中,每次请求时由Cookie中获取session id public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository) {}
- Shiro由于是适用于B/S模式和非B/S模式的安全框架,为了兼容不同环境下Session,Shiro封装了自己的Session接口。在B/S模式下,经过Shiro过滤后,HttpServletRequest、HttpSession就会经过shiro的重新封装,但是封装的过程起始就是代理的过程,操作的具体类实际上还是发送请求的对象。所以,项目中如果集成了Spring-Session,在shiro中对Session的操作实际上还是对Spring封装Session的操作。 B/S模式下Shiro创建的DefaultWebSecurityManager在构造方法中实例化的SessionManager是ServletContainerSessionManager;org.apache.shiro.web.session.HttpServletSession是javax.servlet.http.HttpSession的代理。
public DefaultWebSecurityManager() { super(); ((DefaultSubjectDAO) this.subjectDAO).setSessionStorageEvaluator(new DefaultWebSessionStorageEvaluator()); this.sessionMode = HTTP_SESSION_MODE; setSubjectFactory(new DefaultWebSubjectFactory()); setRememberMeManager(new CookieRememberMeManager()); setSessionManager(new ServletContainerSessionManager()); }
- shiro也提供了禁止其新创建Session的属性,即org.apache.shiro.subject.support.SESSION_CREATION_ENABLED,在shiro Filter执行之前通过其它Filter为request设置这个属性即可。参考如下:
@Service public class DisableShiroSessionFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //禁止shiro创建session request.setAttribute(DefaultSubjectContext.SESSION_CREATION_ENABLED, false); chain.doFilter(request, response); } @Override public void destroy() { } }
相关推荐
包含对于Memcached-Session-Manager配置的五种Tomcat集群session共享机制和策略 jar包及文档
Nginx+Tomcat7+Memcached集群Session共享 完整例子 主要是利用memcached-session-manager(下面简称msm)开源tomcat插件改变tomcat原始的session存储机制,将session的存储放到分布式缓存memcache中,从而实现对...
基于之前支持Tomcat7以下的redis-Session共享机制 进行相关适配的修改打包,里面包含所需Jar包以及相关的说明配置文档,包括:--单点授权Reids配置;- Sentinel 配置 ;- Redis Cluster 配置 ;适用于Tomcat8的容器环境...
集群最有效的方案就是负载均衡,而实现负载均衡用户每一个请求都有可能被分配到不固定的服务器上,这样我们首先要解决session的统一来保证无论用户的请求被转发到哪个服务器上都能保证用户的正常使用,即需要实现...
为了使web应用能使用saas模式的大规模访问,必须实现应用的集群部署.要实现集群部署主要需要实现session共享机制,使得多台应用服务器之间会话统一, tomcat等多数服务都采用了session复制技术实现session的共享
把这种集群间数据共享的机制应用在session同步上,相当于对tomcat第二种集群实现机制进行了优化,既避免了对数据库的依赖,又能达到负载均衡和灾难恢复的效果。在对比测试中,采用Terracotta搭建Tomcat集群,节点...
先说说,这个机制的用途吧,到现在为止战地知道这个机制有两个方面的用途: 首先,多服务器共享session问题,这个大家应该都能够理解的,当一个网站的用户量过大,就会使用服务器集群,例如专门有一个登录用的服务器...
分析:tomcat自身带的机制 session cluster,基于组播的方式,一个tomcat 被用户登录访问,记录session;通过组播给集群中的其他机器复制一份;那么当用户再次访问时,每个机器都有session 会话记录;从而实现了...
1、事务范围(单Session即...在集群环境中,缓存被一个机器或多个机器的进程共享,缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致,缓存中的数据通常采用对象的松散数据形式.
在微服务中我们一般采用的是无状态登录,而传统的session方式,在前后端分离的微服务架构下,如继续使用则必将要解决跨域sessionId问题、集群session共享问题等等。这显然是费力不讨好的,而整合shiro,却很不...
session跨域共享及企业级单点登录解决方案实战 分布式事务解决方案实战 高并发下的服务降级、限流实战 基于分布式架构下分布式锁的解决方案实战 分布式架构实现分布式定时调度 分布式架构-中间件 分布式消息...
在分布式环境中,相同的业务应用分布在不同的机器上,有些业务逻辑(例如一些耗时的计算,网络I/O处理),往往只需要让整个集群中的某一台机器进行执行,其余机器可以共享这个结果,这样可以大大减少重复劳动,提高...
本课程共28节,内容包括nosql基本特点,linux环境下的下载安装与启动,常用命令,配置文件讲解,5种基本数据类型的特点、数存储结构和操作命令,redis安全策略,使用redis实现web服务器的session共享,持久化方式和...
Session共享的问题: 1、tomcat做集群配置session复制。如果集群中节点很多,会形成网络风暴。推荐节点数量不要超过5个。 2、分布式架构。拆分成多个子系统。(本项目使用) ### shop-order(订单系统) * 当...
admin)任务监控、开停、动态修改调度时间策略、手动触发执行jeesuite-security配置简单(初始化一个类即可)满足认证授权基本需求更加贴近日常使用业务场景可选本地session和共享session可选是否支持多端同时登录...
说明: 指定数据库的默认语言, 该语言将用于消息, 日期和月份名, AD, BC, AM 和 PM 的符号, 以及默认的排序机制。可支持的语言包括英语, 法语和日语等等。 值范围: 任何有效的语言名。 默认值: 根据操作系统而定 ...
2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...
2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...