Hi I’m Shendi
SpringBoot共享Session的方法,Redis示例
首先说下Session,Session是服务端对于用户的一次会话
当新的用户访问服务器时,服务器会创建并存储一个信息代表此用户,并响应给浏览器(set-cookie响应头),浏览器会将这个消息保存起来,在下次请求此服务器的时候带上此信息,而服务器通过此信息就知道是哪个用户(会话)了
对于验证码等一些用户的临时数据用Session是比较方便的
传统web应用的Session被单台服务器容器管理,如果要搭建集群,则需要共享Session
Session共享常用有以下几种方法
Tomcat/jetty等容器支持,修改配置即可
多台服务器组成集群,当其中一台有新用户连接,生成session时,会将此session同步到其他服务器,这样就实现了session共享
但是这样会占用比较大的带宽,每台服务器都保存了session,不适合集群
将信息都存到Cookie上,获取信息从Cookie上取,但是Cookie是有大小限制的,而且用户每次请求都会携带Cookie,占用带宽,但可以节省服务器内存开销,而且Cookie容易泄露,所以不能存储重要信息
搭建集群一般用的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
共享session有一个最简单的办法就是将session存储到其他地方,例如Redis,Spring Session就是干这个的
当服务器接到请求,先进入过滤器(Filter),过滤器内将session存储到Redis中,通过Redis来共享Session(将Session从Web容器剥离)
对于使用Session的方法和之前无区别
以Redis作为第三方服务来共享Session
分为两步
@EnableRedisHttpSession
注解来启用Redis接管Session引入依赖,pom加入
org.springframework.boot spring-boot-starter-data-redis
org.springframework.session spring-session-data-redis
启动类加上 @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端口获取
可以在 redis 中看到新增了三个key
在9911端口可以获取到内容,证明session已经共享了
END