淘东电商项目(30) -解决分布式Session共享问题

引言

本文代码已提交至Github(版本号:3b2359205b2d49f9eae313d8cca119082dd7bc99),有兴趣的同学可以下载来看看:https://github.com/ylw-github/taodong-shop

本文主要解决分布式Session的问题。

本文目录结构:
l____引言
l____ 1. 分布式Session的问题
l____ 2. 解决方案
l____ 3. spring-session
l____ 4. 测试
l____总结

1. 分布式Session的问题

1.首先在「淘东电商」项目里复制一个portal-web,并修改端口号为8081,模拟门户集群,如下图:
在这里插入图片描述
2.项目新增controller,作为验证:

@RestController
public class TestSessionController {

    @Value("${server.port}")
    private Integer projectPort;// 项目端口

    @RequestMapping("/createSession")
    public String createSession(HttpSession session, String name) {
        session.setAttribute("name", name);
        return "当前项目端口:" + projectPort + " 当前sessionId :" + session.getId() + "在Session中存入成功!";
    }

    @RequestMapping("/getSession")
    public String getSession(HttpSession session) {
        return "当前项目端口:" + projectPort + " 当前sessionId :" + session.getId() + " 获取的姓名:" + session.getAttribute("name");
    }
}

3.Nginx负载均衡配置:


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;


    keepalive_timeout  65;
  
    upstream  backServer{
	    server 192.168.18.166:8080;
	    server 192.168.18.166:8081;
	}
    server {
        listen       8099;
        server_name  192.168.166.137;
        location / {
           proxy_pass http://backServer;
           index  index.html index.htm;
        }      
    }
}

4.浏览器请求获取session,浏览器请求http://192.168.162.137:8099/getSession

请求一次 请求二次
在这里插入图片描述 在这里插入图片描述

可以看到两次Session的id不一致,并不是我们想要的。那该如何解决呢?下面来讲解决方案。

2. 解决方案

解决方案有如下几种:

  • 使用cookie来完成(缺点:不安全,操作不可靠
  • 使用Nginx中的ip绑定策略,同一个ip只能在指定的同一个机器访问(缺点:不支持负载均衡
  • 利用数据库同步session(缺点:效率不高
  • 使用tomcat内置的session同步(缺点:同步可能会产生延迟
  • 使用token代替session(已经有很好的解决方案了,使用spring-session)
  • 我们使用spring-session以及集成好的解决方案,存放在redis中推荐)。

3. spring-session

step1:首先引入spring-session的maven依赖:

<!--spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
</dependency>

step2:配饰Redis:

spring:
  redis:
    host: 192.168.162.136
    port: 6379
    jedis:
      pool:
        max-idle: 100
        min-idle: 1
        max-active: 1000
        max-wait: -1

step3: 启动类声明允许使用Session共享:

//maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class AppPortalWeb {

    public static void main(String[] args) {
        SpringApplication.run(AppPortalWeb.class, args);
    }
}

4. 测试

启动项目:
在这里插入图片描述
首先浏览器创建session并设置内容到session:http://192.168.162.137:8099/createSession?name=‘ylw’
在这里插入图片描述

浏览器请求:http://192.168.162.137:8099/getSession,可以看到两次的sessionid均为:f8b9a9ab-d285-4b04-8d98-66715cbdc132

请求8080 请求8081
在这里插入图片描述 在这里插入图片描述

打开Medis,可以看到redis已经保存了相关的redis的值:
在这里插入图片描述

总结

本文主要讲解分布式环境下,使用spring-session解决session共享的问题。

发布了2669 篇原创文章 · 获赞 5063 · 访问量 49万+

猜你喜欢

转载自blog.csdn.net/qq_20042935/article/details/104823374
今日推荐