个人博客


在分布式环境中,如果用户在A服务器登录,在下一步操作时如果转发到B服务器,如果这时候没有做Session共享则会导致用户需要再次登录。我们可以使用Redis来缓存Session,然后共享给集群来解决这个问题。

1、Maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
</dependencies>

2、应用配置redis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server:
port: 30600

spring:
application:
name: redis-session
# redis配置
redis:
cluster:
nodes:
- 148.70.153.63:9426
- 148.70.153.63:9427
- 148.70.153.63:9428
- 148.70.153.63:9429
- 148.70.153.63:9430
- 148.70.153.63:9431
password: password
timeout: 60000

这个时候,就已经完成了Session的分布式共享的配置,我们不需要在应用上做任何操作。因为Spring对于Session的缓存和获取已经做了封装,所以对于应用是无感的。我们只需要在应用层获取Session即可。

3、测试验证

1
2
3
4
5
6
7
8
@RestController
public class SessionController {
@RequestMapping("/getSessionId")
public String getSessionId(HttpServletRequest request) {
String sessionId = request.getSession().getId();
return sessionId;
}
}
  1. 在实际应用中,是由Nginx这种反向代理服务器转发给后面的服务器,客户端访问的地址始终是一样的。这里为了方便演示,分别用2个端口3060030700启动服务,代表2台不同的服务器。

  2. 打开浏览器分别访问:
    http://127.0.0.1:30600/getSessionId
    http://127.0.0.1:30700/getSessionId
    可以看到获取的SessionId是一样的,说明2个服务已经共享了Session。

4、指定分布式Session过期时间

server.session.timeout 配置Session过期时间不再生效。
需要通过在启动类添加注解@EnableRedisHttpSession来指定Session过期时间。

1
2
3
4
5
6
7
@SpringBootApplication
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)
public class RedisSessionApplication {
public static void main(String[] args) {
SpringApplication.run(RedisSessionApplication.class, args);
}
}

代码地址