在传统的单服务架构中,一般来说,只有一个服务器,那么不存在 Session 共享问题,但是在分布式/集群项目中,Session 共享则是一个必须面对的问题,先看一个简单的架构图:

java springboot session共享 springboot集群session共享_数据

在这样的架构中,会出现一些单服务中不存在的问题,例如客户端发起一个请求,这个请求到达 Nginx 上之后,被 Nginx 转发到 Tomcat A 上,然后在 Tomcat A 上往 session 中保存了一份数据,下次又来一个请求,这个请求被转发到 Tomcat B 上,此时再去 Session 中获取数据,发现没有之前的数据。对于这一类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是 Redis):

java springboot session共享 springboot集群session共享_Redis_02

当所有 Tomcat 需要往 Session 中写数据时,都往 Redis 中写,当所有 Tomcat 需要读数据时,都从 Redis 中读。这样,不同的服务就可以使用相同的 Session 数据了。

  这样的方案,可以由开发者手动实现,即手动往 Redis 中存储数据,手动从 Redis 中读取数据,相当于使用一些 Redis 客户端工具来实现这样的功能,毫无疑问,手动实现工作量还是蛮大的。

  一个简化的方案就是使用 Spring Session 来实现这一功能,Spring Session 就是使用 Spring 中的代理过滤器,将所有的 Session 操作拦截下来,自动的将数据 同步到 Redis 中,或者自动的从 Redis 中读取数据。

  对于开发者来说,所有关于 Session 同步的操作都是透明的,开发者使用 Spring Session,一旦配置完成后,具体的用法就像使用一个普通的 Session 一样。

代码案列

1.创建一个而简单的springBoot项目

java springboot session共享 springboot集群session共享_Redis_03

web下面勾选如下图所示:

java springboot session共享 springboot集群session共享_redis_04

NoSql选择Redis,如下图所示:

java springboot session共享 springboot集群session共享_数据_05

然后一直下一步就可以了。

配置文件两个:

java springboot session共享 springboot集群session共享_Redis_06

application.yml中的配置如下:

spring:
  profiles:
    active: test

application-test.yml中的配置如下:

spring:
  redis:
    host: 127.0.0.1
    port: 6379
server:
  port: 7009
  servlet:
    context-path: /pay/portal
    session:
      cookie:
        path: /
        name: xkypsession

创建测试Controller:

@Controller
@RequestMapping("/session")
public class SessionController {

    @Value("${server.port}")
    private String port;

    @Autowired
    private RedisTemplate redisTemplate;

    @ResponseBody
    @RequestMapping("/put")
    public String sessionShare(HttpSession session){
            session.setAttribute("session","test");
            return port;
    }

    @ResponseBody
    @RequestMapping("get")
    public String  getSession(HttpSession session){
        return session.getAttribute("session")+",port:"+port;
    }

   
}

本地起两个应用,一个端口7008,另一个端口7009,分别访问,如下所示:

java springboot session共享 springboot集群session共享_数据_07

java springboot session共享 springboot集群session共享_数据_08

到此已经实现了Session共享了;下面看下redis中存储的数据:

java springboot session共享 springboot集群session共享_redis_09