• SpringBoot使用SpringSession和redis解决session共享问题(nginx反向代理)


    Sesssion共享问题是因为在服务器集群下,用户访问服务器将值存放到Session中,再次访问的话代理服务器又会分配一个新的服务器(无法保证这个服务还是之前访问且Session中有数据的服务器),

    这种情况有很多种解决的方案,例如使用nginx的ip绑定,使用cookie,数据库,缓存等等

    最好使用资源最少的情况就是使用SpringSession和Redis来解决

    实现原理大致如下:

    在A服务器中往Session中放入的值,会被SpringSession监听到并写入到redis中,在其他服务器从session取值的时候就会从session找到值并且返回,

    往session中存值和取值都无需手动的吊用redis的API,SpringSession底层会帮助我们实现

    依赖pom.xml

       <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.0.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
            </dependency>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>3.1.0</version>
            </dependency>

    核心配置文件application.properties

    主要是配置redis服务器的参数,和服务端口

    spring.redis.host=192.168.118.3
    spring.redis.port=6379
    spring.redis.password=admin
    #服务器端口
    server.port=6060

    创建一个controller

    用于模拟用户存取数据

    package com.ty.controller;
    
    import org.springframework.beans.factory.annotation.Value;
    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
    public class SessionController {
    
        @Value("${server.port}")
        private String Port;
        @RequestMapping("/setSession")
        public  Object setSession(HttpServletRequest request,String sessionKey,String sessionValue){
            HttpSession httpSession=request.getSession();
            httpSession.setAttribute(sessionKey,sessionValue);
            System.out.println("sessionKey"+sessionKey);
            System.out.println("sessionValue"+sessionValue);
            return "success,port:"+Port;
    
        }
    
        @RequestMapping("/getSession")
        public  Object getSession(HttpServletRequest request,String sessionKey){
            System.out.println("sessionKey:"+sessionKey);
                HttpSession httpSession=null;
                     httpSession = request.getSession(false);
                     String value=null;
            if (httpSession!=null) {
                value=(String) httpSession.getAttribute(sessionKey);
            }
            return "sessionValue:"+value+"---port"+Port;
    
        }
    }

    启动端口为6060的项目,然后修改配置文件,将端口改为6061再次启动,

    把下图中的勾选就可启动两个除端口不一样的两个服务了

    nginx配置(可有可无)

    如果不配置nginx做轮询策略的话,就往a服务器里放入一个数据,在通过b服务器访问这个session用于测试就好了

        upstream backserver { server localhost:6060; server localhost:6061;}
        server {
            listen       80;
            server_name  localhost;
            #charset koi8-r;
            #access_log  logs/host.access.log  main;
            location / {
                proxy_pass http://backserver;
                index index.html index.htm;
            }    
    }

    开始测试

    访问Controller将值放入到session中

    http://localhost/setSession?sessionKey=1&sessionValue=1516

     可以看到将值放入到端接为6061的服务中了,在看看redis中的变化

    redis中保存着一个数据包,包中有session,key就是Session的id

    接着取值

    http://localhost/getSession?sessionKey=1

    由图可见访问端口6060的服务器也是将值给取出来了

    这样就可以解决Session共享的问题

    用nginx解决话就很简单了(不推荐)

    就是在负载均衡的策略下添加ip_hash,根据客户端的ip来决定访问的是哪个服务器,

    这样的话相同的ip永远就会访问到同一个服务器,也就不存在什么Session共享的问题了

        server {
            listen       80;
            server_name  localhost;
    
            #charset koi8-r;
    
            #access_log  logs/host.access.log  main;
            
    
            location / {
                ip_hash
                proxy_pass http://backserver;
                index index.html index.htm;
            }    
    }
  • 相关阅读:
    Spring Boot使用事务不起作用
    Spring的相关注解
    Spring Boot应用启动的三种方式
    Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
    Mysql密码忘记怎么修改?
    第二篇Scrum冲刺博客
    第一篇Scrum冲刺博客
    团队作业4——项目冲刺
    团队作业3--需求改进&系统设计
    项目规范
  • 原文地址:https://www.cnblogs.com/yjc1605961523/p/12298762.html
Copyright © 2020-2023  润新知