分布式session共享问题:
    原因:
    在集群环境中,当客户端发来一个请求,在请求到某台服务器,会在这台服务器上创建sesssion,并且将sessionId存放在响应头中返回,浏览器保存在本地,下次请求,将sessionId存放在请求头中,当下次请求的时候可能请求到的是集群中的另一台服务器,session为空,如果第一次创建session参数设置为true,默认也为true,则会在新的服务器上创建一个新的session,覆盖之前的sessionId,如果设置为false,则不会创建新的session,但都是取不到相应的key-value数据;
    解决办法:
    使用spring-session框架 将session存放到redis缓存中;

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>2.0.0.RELEASE</version>
    5. <relativePath /> <!-- lookup parent from repository -->
    6. </parent>
    7. <properties>
    8. <weixin-java-mp.version>2.8.0</weixin-java-mp.version>
    9. <maven.compiler.source>1.8</maven.compiler.source>
    10. <maven.compiler.target>1.8</maven.compiler.target>
    11. <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
    12. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    13. <project.build.locales>zh_CN</project.build.locales>
    14. </properties>
    15. <dependencies>
    16. <dependency>
    17. <groupId>org.projectlombok</groupId>
    18. <artifactId>lombok</artifactId>
    19. </dependency>
    20. <dependency>
    21. <groupId>org.springframework.boot</groupId>
    22. <artifactId>spring-boot-starter-web</artifactId>
    23. <!-- <exclusions> <exclusion> <groupId>com.fasterxml.jackson.core</groupId>
    24. <artifactId>jackson-databind</artifactId> </exclusion> </exclusions> -->
    25. </dependency>
    26. <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    27. <dependency>
    28. <groupId>com.alibaba</groupId>
    29. <artifactId>fastjson</artifactId>
    30. <version>1.2.47</version>
    31. </dependency>
    32. <!-- Testing Dependencies -->
    33. <dependency>
    34. <groupId>org.springframework.boot</groupId>
    35. <artifactId>spring-boot-starter-test</artifactId>
    36. <scope>test</scope>
    37. </dependency>
    38. <dependency>
    39. <groupId>org.springframework.boot</groupId>
    40. <artifactId>spring-boot-starter-data-redis</artifactId>
    41. </dependency>
    42. <!--spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
    43. <dependency>
    44. <groupId>org.springframework.session</groupId>
    45. <artifactId>spring-session-data-redis</artifactId>
    46. </dependency>
    47. <dependency>
    48. <groupId>org.apache.commons</groupId>
    49. <artifactId>commons-pool2</artifactId>
    50. </dependency>
    51. <dependency>
    52. <groupId>redis.clients</groupId>
    53. <artifactId>jedis</artifactId>
    54. </dependency>
    55. </dependencies>
    56. <build>
    57. <plugins>
    58. <plugin>
    59. <groupId>org.apache.maven.plugins</groupId>
    60. <artifactId>maven-compiler-plugin</artifactId>
    61. <configuration>
    62. <source>1.8</source>
    63. <target>1.8</target>
    64. </configuration>
    65. </plugin>
    66. <plugin>
    67. <groupId>org.springframework.boot</groupId>
    68. <artifactId>spring-boot-maven-plugin</artifactId>
    69. <configuration>
    70. <maimClass>com.meiteedu.WxMpApplication</maimClass>
    71. </configuration>
    72. <executions>
    73. <execution>
    74. <goals>
    75. <goal>repackage</goal>
    76. </goals>
    77. </execution>
    78. </executions>
    79. </plugin>
    80. </plugins>
    81. </build>
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
    import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
    
    //这个类用配置redis服务器的连接
    //maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)
    @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
    public class SessionConfig {
    
        // 冒号后的值为没有配置文件时,制动装载的默认值
        @Value("${redis.hostname:localhost}")
        String HostName;
        @Value("${redis.port:6379}")
        int Port;
    
        @Bean
        public JedisConnectionFactory connectionFactory() {
            JedisConnectionFactory connection = new JedisConnectionFactory();
            connection.setPort(Port);
            connection.setHostName(HostName);
            return connection;
        }
    }
    
    //初始化Session配置
    public class SessionInitializer extends AbstractHttpSessionApplicationInitializer{
        public SessionInitializer() {
            super(SessionConfig.class);
        }
    }
    

    应用Token令牌方式替换sesion,因为token本来就是存放在redis里边的;

    @Service
    public class TokenService {
        @Autowired
        private RedisService redisService;
    
        // 新增 返回token
        public String put(Object object) {
            String token = getToken();
            redisService.setString(token, object);
            return token;
        }
    
        // 获取信息
        public String get(String token) {
            String reuslt = redisService.getString(token);
            return reuslt;
        }
    
        public String getToken() {
            return UUID.randomUUID().toString();
        }
    
    }
    
    @RestController
    public class TokenController {
        @Autowired
        private TokenService tokenService;
        @Value("${server.port}")
        private String serverPort;
    
        @RequestMapping("/put")
        public String put(String nameValue) {
            String token = tokenService.put(nameValue);
            return token + "-" + serverPort;
        }
    
        @RequestMapping("/get")
        public String get(String token) {
            String value = tokenService.get(token);
            return value + "-" + serverPort;
        }
    
    }
    

    itmayiedu_session.zip 分布式Session一致性问题.docx

    session集群.pngsession原理.png反向代理.png分布式解决方案.png