分布式-Session共享问题

一、分布式环境下的Session问题

  在单体应用时代,我们不需要考虑Session不同步的问题,但在分布式系统中,因为Http协议是⽆状态的协议,客户端和服务端在某次会话中产⽣的数据不会被保留下来,所以第⼆次请求服务端⽆法认识到你曾经来过。

   Http为什么要设计为⽆状态协议?早期都是静态⻚⾯⽆所谓有⽆状态,后来有动态的内容更丰富,就需要有状态,出现了两种⽤于保持Http状态的技术,那就是Cookie和Session。单体应用时代依靠Cookie和Session成功实现了记录登录状态的功能,可session是在服务器端存储的,在分布式系统中每次访问可能是不同的服务器,导致session未被找到,而导致重复登录问题,如下图。

分布式-Session共享问题_第1张图片

 

 二、解决Session⼀致性的⽅案

 2.1 Nginx的 IP_Hash 策略(可以使用)

    修改nginx的配置文件,这样同⼀个客户端IP的请求都会被路由到同⼀个⽬标服务器,也叫做会话粘滞,这样就解决了session找不到问题。

#配置负载服务
upstream mylogin{
        ip_hash;
        server 127.0.0.1:8080;
		server 127.0.0.1:8081;
    }
server {
        listen       80;
        server_name  localhost;

        #配置路径和服务
		location / {
             proxy_pass http://mylogin/;
        }
}

    使用这种方式优点是配置简单,不⼊侵应⽤,不需要额外修改代码,但也有不少缺点,如服务器重启Session丢失、存在单点负载⾼的⻛险等问题。

 2.2 Session复制(不推荐)

多个tomcat之间通过修改配置⽂件,达到Session之间的复制。




    
    
        
        
        
        
            
        
        
        
    
    
    
    
    

 


  这种方式优点也是不⼊侵应⽤,服务器重启或者宕机不会造成Session丢失。但因为需要数据同步,导致性能低,有延迟性。

 2.3 Spring Session基于redis实现Session共享(推荐)

    Spring Session提供了多种方式来存储Session信息,包括redis、mongo、gemfire、hazelcast、jdbc等。这里用redis来举例说明,首先进行依赖添加,然后进行配置即可。

  2.3.1 引入jar包

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

  2.3.2 配置redis

spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379

  2.3.3 添加注解@EnableRedisHttpSession

@SpringBootApplication
@EnableCaching
@EnableRedisHttpSession
public class LoginApplication extends SpringBootServletInitializer {

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

   这种方式能适应各种负载均衡策略,同时扩展能力强,唯一缺点就是对代码有一些侵入性,但好在因为springboot的强大装配功能,使得配置比较简单。

    扩展一下,通过观察源码,会发现实际springsession有一个核心Filter去对session做了存取。

 

分布式-Session共享问题_第2张图片 

 

你可能感兴趣的:(分布式,分布式,session)