• 分布式session的4种解决方案


    分布式session的4种解决方案

    1、cookie和session
    cookie和session都是用来跟踪用户身份信息的会话方式。
    cookie存储的数据保存在本地客户端,用户获取容易,但安全性不高,存储数据小。
    session存储的数据保存在服务器,用户不易获取,安全性较高,存储数据较大。
    通常情况下,服务器将用户信息通过session的方式保存在服务器,然后将sessionId返回给客户端cookie,客户端进行下次请求时,就可在cookie中带上sessionId,服务器通过sessionId,就可以在服务器内存中找到对应的session对象,获取当前用户的信息。

    流程可如下所示:
    在这里插入图片描述
    2、背景介绍
    传统项目中,单服务器场景,服务器的session对象保存在本地内存,浏览器的每次请求都会打到该服务器上,所以,只要session没过期,一定能够获取到session对象。

    但在多服务器场景,或微服务项目中,一个工程有多个实例。浏览器的多次请求,经过nginx反向代理后,有可能就会请求到不同的服务器上。场景如下所示:
    在这里插入图片描述
    3、解决方案
    3.1、session复制
    session同步,让集群下的服务器进行session同步,一种传统的服务器集群session管理机制,常用于服务器不多的集群环境。

    集群下,进行session同步的服务器的session数据是相同的,任何一台服务器挂掉,都不会丢失用户的session数据。

    但是,session同步是通过广播的方式来异步同步session,会通过网络进行数据传输。当服务器越来越多时,session同步会占用大量带宽,并且每台服务器需要存储的session数据也越来越大,占用大量服务器内存。

    所以,session同步策略一般适用于集群服务器不多的场景。
    3.2、客户端存储(不推荐)
    直接将session数据存储到浏览器的cookie中,浏览器在发起请求时,通过cookie将session数据发送给客户端。因为cookie不安全,易获取,所以通常用来存储一些不敏感的信息。

    但是,由于cookie不安全,且每次http请求,都会携带存储在cookie中的完整用户信息,会增大网络传输开销,并且cookie有存储大小限制。所以基本上不会使用这种方式。

    3.3、Hash一致性
    修改nginx的负载均衡配置,设置为ip-hash策略,将客户端与服务器进行绑定,让来自同一ip的请求,全都转发到同一台服务器。

    此方案配置简单,但有一台服务器挂掉之后,该服务器上的session信息将全部丢失,与该服务器绑定的客户端,必须得重新登录。并且在进行水平扩展时,会重新对客户端ip进行hash操作,部分ip会被重新映射服务器。

    # 配置负载均衡服务器组名称和地址
    upstream web_server {
        ip_hash;
        server 192.168.12.36;
        server 192.168.12.37;
        server 192.168.12.38;
    }
     
    # nginx路由配置
    server {
        listen       8080;
        server_name  localhost;
        location / {
            proxy_pass http://web_server;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.4、基于Redis的分布式session(推荐)
    将集群下所有服务器的session都存储到redis集群中。

    直接使用Spring封装的Spring Session,引入相关依赖,使用简单,session数据保存在redis中,无缝接入,无安全隐患;且Redis也可做主从集群架构,方便管理。唯一的缺点是,服务器需要与Redis做一次网络交互,多了点网络开销。
    在这里插入图片描述

    3.4.1、引入相关依赖
    <dependency>
      <groupId>org.springframework.session</groupId>
      <artifactId>spring-session</artifactId>
    </dependency>
     
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
     
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.4.2、Java 配置

    @Configuration
    @EnableRedisHttpSession 
    public class Config {
    	@Bean
    	public LettuceConnectionFactory connectionFactory() {
    		return new LettuceConnectionFactory(); 
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.4.3、Redis配置

    spring.redis.host=localhost
    spring.redis.port=6379
    spring.redis.password=123456
    spring.redis.database=0
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    图解LeetCode——662. 二叉树最大宽度(难度:中等)
    微信小程序-语音输入(录音并播放)
    Flink集群部署
    PMP考试难度大吗?
    详情讲解canvas实现电子签名
    优测云测试平台 | 有效的单元测试(下)
    JS实现:统计字符出现频率/计算文字在文本中的出现次数
    写一个flutter程序
    PTA 7-78 烤肉饼(*)
    技术分享 | Jenkins通过什么方式报警?
  • 原文地址:https://blog.csdn.net/weixin_45817985/article/details/132651035