通过LVS或者Nginx等进行负载均衡(一般使用Nginx+Tomcat实现负载均衡)
如果我们采用的spring集成shiro,其实可以将缓存管理器交由spring管理,相当于由spring统一管理缓存。
shiro的session创建时机是在登录认证之前,而不是第一次调用getSession()时。
● 第一种是使用容器扩展插件来实现,比如基于Tomcat的tomcat-redis-session-manager插件,基于Jetty的jetty-session-redis插件、memcached-session-manager插件;这个方案的好处是对项目来说是透明的,无需改动代码,但是由于过于依赖容器,一旦容器升级或者更换意味着又得重新配置
其实底层是,复制session到其它服务器,所以会有一定的延迟,也不能部署太多的服务器。
● 第二种是使用Nginx负载均衡的ip_hash策略实现用户每次访问都绑定到同一台具体的后台tomcat服务器实现session总是存在
这种方案的局限性是ip不能变,如果手机从北京跳到河北,那么ip会发生变化;另外负载均衡的时候,如果某一台服务器发生故障,那么会重新定位,也会跳转到别的机器。
● 第三种是自己写一套Session会话管理的工具类,在需要使用会话的时候都从自己的工具类中获取,而工具类后端存储可以放到Redis中,这个方案灵活性很好,但开发需要一些额外的时间。
● 第四种是使用框架的会话管理工具,也就是我们要介绍的Spring session,这个方案既不依赖tomcat容器,又不需要改动代码,由Spring session框架为我们提供,可以说是目前非常完美的session共享解决方案
shiro源码篇 - shiro的session共享,你值得拥有
1、同域名下不同项目实现Session共享
-
在同一个域名下,比如:
-
有多个不同的项目
做法:设置Cookie路径为根/上下文;
2、同根域名不同二级子域名下的项目实现Session共享
-
同一个根域名,比如:
-
beijing.web.com
-
nanjing.web.com
-
不同的二级子域名
做法:
-
设置Cookie路径为根/上下文
-
设置Cookie域名为同域名 .web.com
Spring Session
Spring Session为企业级Java应用的session管理带来了革新,使得以下的功能更加容易实现:
-
编写可水平扩展的原生云应用。
-
将session所保存的状态卸载到特定的外部session存储中,如Redis或Apache Geode中,它们能够以独立于应用服务器的方式提供高质量的集群。
-
当用户使用WebSocket发送请求的时候,能够保持HttpSession处于活跃状态。
-
在非Web请求的处理代码中,能够访问session数据,比如在JMS消息的处理代码中。
-
支持每个浏览器上使用多个session,从而能够很容易地构建更加丰富的终端用户体验。
-
控制session id如何在客户端和服务器之间进行交换,这样的话就能很容易地编写Restful API,因为它可以从HTTP 头信息中获取session id,而不必再依赖于cookie。
需要说明的很重要的一点就是,Spring Session的核心项目并不依赖于Spring框架,所以,我们甚至能够将其应用于不使用Spring框架的项目中。
每个用户有多个账号
假设我们在example.com上运行面向公众的Web应用,在这个应用中有些用户会创建多个账号。例如,用户Jeff Lebowski可能会有两个账户thedude@example.com和lebowski@example.com。和其他Java Web应用一样,我们会使用HttpSession
来跟踪应用的状态,如当前登录的用户。所以,当用户希望从thedude@example.com切换到lebowski@example.com时,他必须要首先退出,然后再重新登录回来。
借助Spring Session,为每个用户配置多个HTTP session会非常容易,这样用户在thedude@example.com和lebowski@example.com之间切换的时候,就不需要退出和重新登录了。
多级别的安全预览
典型的Web应用会将当前用户的标识及其角色保存在HTTP session中,但因为在Web应用中,每个登录的用户只能有一个session,因此除了用户退出并重新登录进来,我们并没有办法在角色之间进行切换,除非我们为每个用户自行实现多个session的功能。
借助Spring Session,可以很容易地为每个登录用户创建多个session,这些session之间是完全独立的,因此实现上述的预览功能是非常容易的。例如,当前用户以top secret角色进行了登录,那么应用可以创建一个新的session,这个session的最高安全角色是secret而不是top secret,这样的话,用户就可以在secret模式预览应用了。
当使用Web Socket的时候保持登录状态
假设用户登录了example.com上的Web应用,那么他们可以使用HTML5的chat客户端实现聊天的功能,这个客户端构建在websocket之上。按照servlet规范,通过websocket传入的请求并不能保持HTTP session处于活跃状态,所以当用户在聊天的过程中,HTTP session的倒数计时器会在不断地流逝。即便站在用户的立场上,他们一直在使用应用程序,HTTP session最终也可能会出现过期。当HTTP session过期时,websocket连接将会关闭。
借助Spring Session,对于系统中的用户,我们能够很容易地实现websocket请求和常规的HTTP请求都能保持HTTP session处于活跃状态。
非Web请求访问Session数据
假设我们的应用提供了两种访问方式:一种使用基于HTTP的REST API,而另一种使用基于RabbitMQ的AMQP消息。执行消息处理代码的线程将无法访问应用服务器的HttpSession,所以我们必须要以一种自定义的方案来获取HTTP session中的数据,这要通过自定义的机制来实现。
通过使用Spring Session,只要我们能够知道session的id,就可以在应用的任意线程中访问Spring Session。因此,Spring Session具备比Servlet HTTP session管理器更为丰富的API,只要知道了session id,我们就能获取任意特定的session。例如,在一个传入的消息中可能会包含用户id的header信息,借助它,我们就可以直接获取session了。
Spring Session对HTTP的支持
Spring Session对HTTP的支持是通过标准的servlet filter来实现的,这个filter必须要配置为拦截所有的web应用请求,并且它应该是filter链中的第一个filter。Spring Session filter会确保随后调用javax.servlet.http.HttpServletRequest
的getSession()
方法时,都会返回Spring Session的HttpSession
实例,而不是应用服务器默认的HttpSession。
配置Spring Session
在Web项目中配置Spring Session分为四步:
-
搭建用于Spring Session的数据存储
-
将Spring Session的jar文件添加到web应用中
-
将Spring Session filter添加到web应用的配置中
-
配置Spring Session如何选择session数据存储的连接
每个浏览器多个Session
Spring Session会为每个用户保留多个session,这是通过使用名为“_s
”的session别名参数实现的。例如,如果到达的请求为http://example.com/doSomething?_s=0 ,那么Spring Session将会读取“_s”参数的值,并通过它确定这个请求所使用的是默认session。
Spring Session 结论
Spring Session为企业级Java的session管理带来了革新,使得如下的任务变得更加容易:
-
编写可水平扩展的原生云应用。
-
将session所保存的状态卸载到特定的外部session存储中,如Redis或Apache Geode中,它们能够以独立于应用服务器的方式提供高质量的集群。
-
当用户使用WebSocket发送请求的时候,能够保持HttpSession处于活跃状态。
-
在非Web请求的处理代码中,能够访问session数据,比如在JMS消息的处理代码中。
-
支持每个浏览器上使用多个session,这样就可以很容易地构建更加丰富的终端用户体验。
-
控制客户端和服务器端之间如何进行session id的交换,这样更加易于编写Restful API,因为它可以从HTTP 头信息中获取session id,而不必再依赖于cookie。