Springboot系列-整合Session共享

Springboot系列-整合Session共享

前言:大家可能都清楚Web三大概念:cookie、session、application,因此对session也并不陌生,此篇博客将主要针对于session以及session的整合做出介绍

1.关于Session

简介:Session与cookie功能效果一样,Session与Cookie的区别在于Session是记录在服务端的,而Cookie是记录在客户端的

举例:当访问服务器否个网页时,会在服务器端的内存里开辟一块新的内存,这块内存就叫做session,而这块内存是跟浏览器关联在一起的,这个浏览器指的是当前访问的浏览器窗口,换句话说就是只允许当前这个session对应的浏览器访问,即使在同一个机器上新启的浏览器也是无法访问的,而另外一个浏览器如果也需要记录session的话,就会再启一个新的session

原理:HTTP协议是非连接性的,获取到当前浏览器数据之后关闭浏览器,链接就断开了,没有任何机制去记录取出后的信息 ;当访问同一个网站的另外一个页面时,同样上个页面的信息将无法读取,所以需要有一种机制让页面知道原来页面的session内容

解决:当访问一个页面时给浏览器创建一个唯一标识,同时也赋给创建的session同样的标识,这样就可以在打开同一个网站的第二个页面时获取到第一个页面中session保留下来的对应信息,这个号码也叫sessionID

实现(传递方式):1)通过cookies实现:因为cookie有临时的,也有定时的,临时的就是当前浏览器关掉即消失,也就是说session本来就是当浏览器关闭即消失的,所以把session的id 放在cookie里,当允许浏览器使用cookie时,session就会依赖于cookies。2)通过URL重写:在浏览器不支持cookies情况下通过url重写来实现,通过response.encodeURL()方法,这个方法第一个作用是支持转码,第二个作用在encodeUTL()后面跟上sessionID后,及时在禁用cookie的浏览器中也可以使用session,所以在cookies不能用情况下想用session就必须加上encodeURL(),如:

out.println("")
out.println("reload)
out.println("")

2.使用session

在传统的单服务架构中,一般来说只有一个服务器,那么不存在 Session 共享问题,但是在分布式/集群项目中,Session 共享是不可或缺的,先看如图:
Springboot系列-整合Session共享_第1张图片

上图架构中,会出现一些单服务中不存在的问题,例如客户端发起一个请求,请求到 Nginx 上之后,被 Nginx 通过轮询等方式转发到 Tomcat1上,然后在 Tomcat 1 的 session 中保存了一份数据,第二个请求到达时,这个请求被转发到 Tomcat 2 上,此时再去 Session 中获取数据,发现没有之前的数据,原因是没有共享session,那么如何解决呢?简言之就是将各个服务之间需要共享的数据,保存到一个公共的地方,如下:

Springboot系列-整合Session共享_第2张图片

可以看出和第一个架构图相比,多了一个redis,正因如此当所有 Tomcat 需要往 Session 中写数据时,都往 Redis 中写,当所有 Tomcat 需要读数据时,都从 Redis 中读,所以不同的服务就可以使用相同的 Session 数据

为了简化开发者手动向redis存读数据,我们将使用spring session 来解决这一问题,Spring Session 就是使用 Spring 中的代理过滤器,将所有的 Session 操作拦截下来,自动的将数据 同步到 Redis 中,或者自动的从 Redis 中读取数据


3.项目实战

接下来我们对于spring session进行实践整合

1.首先创建一个 Spring Boot 工程,引入redis
Springboot系列-整合Session共享_第3张图片

2.pom.xml文件依赖如下:


    org.springframework.session
    spring-session-data-redis


    org.springframework.boot
    spring-boot-starter-data-redis


    org.springframework.boot
    spring-boot-starter-web

3.在配置文件中配置redis

spring.redis.host=62.234.17.94
spring.redis.port=6379
spring.redis.password=123456
spring.redis.database=0

4.配置完成后,就可以使用 Spring Session了,换句话说就是使用 HttpSession ,其他的 Session 同步到 Redis 等操作,创建一个controller:

@RestController
public class SessionController {
    //集群方式启动,通过端口号区分服务
    @Value("${server.port}")
    Integer port;

    @GetMapping("/set")
    public String set(HttpSession session){
        session.setAttribute("user","王帅帅");
        return String.valueOf(port);
    }
    
    @GetMapping("/get")
    public String get(HttpSession session){
         return session.getAttribute("user")+":"+port;
    }
}

5.项目打包,不过许多人在打包的时候会遇到一些瓶颈,比如控制台会报错:Caused by : not connection 62.234.17.64:6379 或者 "您主机上的软件终止了建立的链接" 以及 (error) DENIED Redis is running in protected mode because protected mode is enabled等,解决办法如下:

  • 修改redis.conf配置文件 (yes - > no): protected-mode:no
  • 修改redis.conf配置文件(yes - > no): daemonize no
  • 修改redis.conf配置文件 注释掉绑定ip:# bind 127.0.0.1
  • 启动redis时指定配置文件 : ./redis-server ../redis.conf
  • 还有一个关键点redis.conf配置文件中如果设置了requirepass密码,在springboot的配置文件中也要加上对应密码,如果配置文件密码被注释掉了,则配置文件中不需要配置密码

Springboot系列-整合Session共享_第4张图片

6.项目打包成功之后,将jar包部署到服务器上,启动项目的两个实例

java -jar session-0.0.1-SNAPSHOT.jar --server.port=8081
java -jar session-0.0.1-SNAPSHOT.jar --server.port=8082

7.先访问set接口,向8081服务的session中保存一个变量,访问完成之后数据会自动同步到redis中,然后调用get接口,就可以获取到8081服务session中的数据
Springboot系列-整合Session共享_第5张图片

到这关于 session 共享的配置就已经全部完成,但是我们会发现每次访问都是自己手动切换服务实例,因此,这里需要引入 Nginx ,实现服务实例自动切换

结语:【end】

你可能感兴趣的:(springboot系列)