SpringBoot共享Session的方法,Redis示例

专栏收录该内容

Hi I'm Shendi



首先说下Session,Session是服务端对于用户的一次会话

当新的用户访问服务器时,服务器会创建并存储一个信息代表此用户,并响应给浏览器(set-cookie响应头),浏览器会将这个消息保存起来,在下次请求此服务器的时候带上此信息,而服务器通过此信息就知道是哪个用户(会话)了

对于验证码等一些用户的临时数据用Session是比较方便的


Session共享

传统web应用的Session被单台服务器容器管理,如果要搭建集群,则需要共享Session

Session共享常用有以下几种方法


Session复制

Tomcat/jetty等容器支持,修改配置即可


多台服务器组成集群,当其中一台有新用户连接,生成session时,会将此session同步到其他服务器,这样就实现了session共享

但是这样会占用比较大的带宽,每台服务器都保存了session,不适合集群



浏览器存储

将信息都存到Cookie上,获取信息从Cookie上取,但是Cookie是有大小限制的,而且用户每次请求都会携带Cookie,占用带宽,但可以节省服务器内存开销,而且Cookie容易泄露,所以不能存储重要信息



Nginx Hash一致性

搭建集群一般用的nginx,负载均衡将请求随机分配或者平摊到其他服务器上,session不一致是因为用户访问了不同服务器导致的,如果能保证用户每次都访问的相同的服务器,那么就可以解决

在nginx配置负载均衡内增加 ip_hash,这样相同ip的就会访问相同的服务器

upstream test {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    ip_hash;
}

但重启服务器会导致session丢失,且不能共享,对Session要求不高,仅仅是用作验证码可以使用此方法



Spring Session

Spring的会话管理工具,推荐使用这种方法来共享Session

共享session有一个最简单的办法就是将session存储到其他地方,例如Redis,Spring Session就是干这个的

当服务器接到请求,先进入过滤器(Filter),过滤器内将session存储到Redis中,通过Redis来共享Session(将Session从Web容器剥离)


对于使用Session的方法和之前无区别



以Redis作为第三方服务来共享Session

分为两步

  1. 引入依赖
  2. 给启动类加上 @EnableRedisHttpSession 注解来启用Redis接管Session

引入依赖,pom加入

<!-- SpringDataRedis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 用于redis接管session -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

启动类加上 @EnableRedisHttpSession 注解

@SpringBootApplication
@EnableRedisHttpSession
public class Application {

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


测试

配置好redis,加两个接口,一个获取session内容,一个设置session内容,例如

@RestController
public class UserControl {
	
	@GetMapping("/get")
	public String get(HttpServletRequest req) {
		String name = (String) req.getSession().getAttribute("name");
		System.out.println(name);
		return name;
	}
	
	@GetMapping("/set")
	public String set(HttpServletRequest req, String name) {
		req.getSession().setAttribute("name", name);
		return "设置成功";
	}
	
}

启动SpringBoot,然后更改端口在启动一个,例如端口为9910和9911,启动完成后,可以尝试下在9910调用set接口设置session内容,然后在9911端口获取

设置session


可以在 redis 中看到新增了三个key

session在redis中存储的key

在9911端口可以获取到内容,证明session已经共享了

Session获取




END

本文链接:https://sdpro.top/blog/html/article/1026.html

♥ 赞助 ♥

尽管去做,或许最终的结果不尽人意,但你不付出,他不付出,那怎会进步呢?