一、spring session 共享的实现原理
单个应用的session应用
- 用户登陆之后,将状态信息保存到session里面。服务端自动维护sessionid,即将sessionid写入cookie。
- cookie随着HTTP响应,被自动保存到浏览器端。
- 当用户再次发送HTTP请求,sessionid随着cookies被带回服务器端
- 服务器端根据sessionid,可以找回该用户之前保存在session里面的数据。
集群应用的Session共享
- 同一IP(域名),不同端口,在同一个浏览器cookies是共享的。不同IP(域名)的Cookies,在同一个浏览器Cookies肯定不共享的。对于这种情况需要在集群应用的前面加上负载均衡器逆向代理,如:nginx,haproxy。让客户端看上去访问的是同一个IP(代理IP),从而浏览器认为基于这个IP的Cookies是共享的。
- SESSION正常是由Servlet容器来维护的(内存里面,每个服务器内存是不共享的),这样SESSION就无法共享。如果希望Session共享,就需要把sessionID的存储放到一个统一的地方,如:redis。SessionID的维护交给Spring session则更加方便。
- 除了Cookies可以维持Sessionid,Spring Session还提供了了另外一种方式,就是使用header传递SESSIONID。目的是为了方便类似于手机这种没有cookies的客户端进行session共享。
不要把跨域请求和cookies跨域名的概念搞混了。同源策略是要求IP、端口、协议全一致,不一致的请求就是跨域请求。但cookies是可以跨域共享的,但是不能跨域名(IP)共享。
二、集成Spring session
1.引入spring-session-redis的maven依赖
项目内引入spring-session-data-redis
,配合spring-boot-starter-data-redis
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.配置启用Redis的httpSession
在启动类上方加上注解,启动SpringSession管理应用的session,并设置session数据的有效期30分钟
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 30 * 60 * 1000)
3.配置redis链接信息(application.yml)
配置redis链接信息
spring:
redis:
database: 0
host: 这里填写redis服务ip
password: 这里填写redis服务密码
port: 6379
4.测试
做好上文的配置之后,并加入如下的测试代码,后文测试的时候会用到
@Controller
public class SessionController {
@RequestMapping(value="/uid",method = RequestMethod.GET)
public @ResponseBody
String uid(HttpSession session) {
return "sessionId:" + session.getId();
}
}
5. 一个项目多个端口启动
为了实现验证一个应用的多个实例的session共享,我们启动多个服务实例
- 点击edit configuration ,取消勾选single instance only(只允许单节点运行)。在比较新的版本中这个勾选框变成了Allow parallel run(允许多实例并发运行),那你就给它勾选上。总之我们是要运行多实例。
- 复制一份当前配置,在environment选项中的vm options 中设置不同的端口号
-Dserver.port=8889 -Dserver.httpPort=89 -Dspring.profiles.active=dev -Ddebug
-Dserver.port=8888 -Dserver.httpPort=88 -Dspring.profiles.active=dev -Ddebug
三、测试
依次访问,看看效果.通过返回值session.getId()
即:sessionid来判断,如果sessionid一致,则证明session共享成功了。
用浏览器访问下面的地址,自己看一下效果,再理解一下。
因为我们在同一台机器上启动多个实例,ip相同所以session是共享的。如果你在不同的服务器上启动多个实例(IP)不同,你需要在应用前方加上负载均衡逆向代理才可以实现session共享。(如本文首图)