文章目录
- 前言
- 第一节 传统的单点登录示例
- 第二节 如何解决多服务器session共享的问题
- 1. 安装redis
- 2. session共享实践
- 3. 登出
前言
通常我们的session保存在服务器内存中,那么当我们部署多台服务器时,如何实现session共享?
第一节 传统的单点登录示例
- 新建一个springboot 项目,引入web-starter和lombok
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
- 添加模拟登录登出的代码
package com.it2.springbootsession01.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@RestController
@RequestMapping("/sessiontest")
@Slf4j
public class SessionTestController {
/**
* 登录
* @param request
* @param name
* @return
*/
@GetMapping("/login")
public String login(HttpServletRequest request, String name) {
log.info("登录:{}", name);
HttpSession session = request.getSession();
session.setAttribute("name", name);
return name + " login success";
}
/**
* 登出
* @param request
* @return
*/
@GetMapping("/logout")
public String logout(HttpServletRequest request) {
HttpSession session = request.getSession();
String name= session.getAttribute("name") + "";
session.removeAttribute("name");
log.info("登出:{}", name);
return name + " logout success";
}
/**
* 获取用户名
* @param request
* @return
*/
@GetMapping("/getusername")
public String getUsername(HttpServletRequest request) {
HttpSession session = request.getSession();
return "hello," + session.getAttribute("name") + "";
}
}
- 启动服务器测试demo是否正常。可以看到登录成功,并且能够获取到用户名。
模拟多服务器,此时在8089再启动一台服务器
可以发现8089这台服务器并不能获取到用户名,说明session未在多服务器之间共享。server1登录后,server2无法获取到server1的登录信息(session)。
第二节 如何解决多服务器session共享的问题
我们只需要将session存储到DB里面,两台server共享DB,即可实现sesssion共享。
springboot提供了mongodb、redis、jdbc、hazelcast(一款分布式缓存)等方案。
这里我们选择redis作为session共享方案,redis作为noSQL数据库,其性能非常优秀。由于采用了外部的DB存储,所以多节点的部署可以既可以在同一台物理机器上,也可以在不同的物理机器上,没有地理的限制。
那么具体如何实现session共享呢?
1. 安装redis
由于选择了redis的方案,所以需要先拥有一台可用的redis服务器。如果已经有redis,可以忽略。
安装方案:
- docker安装redis的方案:
docker run -d --name redis -p 6379:6379 -d redis:latest
- windows安装redis方案
一路next即可,没啥难度。
可参考: https://www.redis.com.cn/redis-installation.html - 管理redis的可视化工具
RedisDesktopManager
一款桌面的redis管理工具,可以辅助用户查看redis里面的数据,对数据进行操作和管理。
2. session共享实践
下面我们基于前面的代码对项目进行修改,使其实现多服务器之间的session共享。
- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
- 配置spring-session方案
spring:
session:
timeout: 7200 #session失效时间,单位秒
store-type: redis #spring-session存储配置
redis:
port: 6379
host: localhost
database: 15 #指定存入redis的哪个库,默认0,可配可不配,这里指定只是为了将登录的内容单独存储
- 两个服务都启动,在其中一台服务器进行登录测试,如果两台服务器都能获取到username即视为session实现了共享。
到此,基于redis的多服务器session共享成功。
3. 登出
执行登出操作,可以看到两个服务器都不能获取username,则表明单点登出,多节点都会登出。