springboot基础:多节点登录session共享

前言

通常我们的session保存在服务器内存中,那么当我们部署多台服务器时,如何实现 session共享

传统的单点登录示例

  1. 新建一个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>
  1. 添加模拟登录登出的代码
package com.summergao.sessiontest.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") + "";
    }
}

3. 启动服务器测试demo是否正常。可以看到登录成功,并且能够获取到用户名。

http://localhost:8081/sessiontest/login?name=SummerGao

http://localhost:8081/sessiontest/getusername

4. 模拟多服务器,此时在8082再启动一台服务器

-Dserver.port=8082

http://localhost:8082/sessiontest/getusername

可以发现8082这台服务器并不能获取到用户名,说明session未在多服务器之间共享。server1登录后,server2无法获取到server1的登录信息(session)。

如何解决多服务器session共享的问题?

我们只需要将session存储到DB里面,两台server共享DB,即可实现sesssion共享。

springboot提供了mongodb、redis、jdbc、hazelcast(一款分布式缓存)等方案。
这里我们选择redis作为session共享方案,redis作为noSQL数据库,其性能非常优秀。由于采用了外部的DB存储,所以多节点的部署可以既可以在同一台物理机器上,也可以在不同的物理机器上,没有地理的限制。
那么具体如何实现session共享呢?

由于选择了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里面的数据,对数据进行操作和管理。

session共享实践

下面我们基于前面的代码对项目进行修改,使其实现多服务器之间的session共享。

  1. 导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
  1. 配置spring-session方案
spring:
  # session配置
  session:
    timeout: 86400 # 设置session失效时间
    store-type: redis # 修改spring-session存储配置,默认存储到服务器内存中,现在设置存到redis中(关键)
  # redis配置
  redis:
    port: 6379 # redis的端口号(这里是我的redis容器在docker中对应的端口号)
    host: localhost # redis服务器ip
    password:  # 密码(默认为空)
    database: 0 # 设置存入redis的哪一个库(默认是0)

3. 两个服务都启动,在其中一台服务器进行登录测试,如果两台服务器都能获取到username即视为session实现了共享。

到此,基于redis的多服务器session共享成功。

登出

执行登出操作,可以看到两个服务器都不能获取username,则表明单点登出,多节点都会登出。

http://localhost:8081/sessiontest/logout

猜你喜欢

转载自blog.csdn.net/qq_25231683/article/details/129969877