• [分布式]分布式会话session、spring-session


    分布式会话

    资料

    前端鉴权的兄弟们:cookie、session、token、jwt、单点登录 - 掘金

    分布式Session一致性的4种解决方案 - SegmentFault 思否

    问题的提出

    http是无状态的, 无法区分不同用户的请求(request); 为了解决这个问题, 传统的解决方法是cookie+session;

    基于cookie+session登录校验流程:

    单体服务的session一般存储在服务的内存里, 当服务集群化/分布式部署时, 不同服务上存储的session可能不同, 导致会话混乱, 出现"分布式会话"的问题;

    如果服务端是集群,用户请求过来会走一次负载均衡,不一定打到哪台机器上。一旦用户后续接口请求到的机器和他登录请求的机器不一致,或者登录请求的机器宕机了,session就失效了

    解决办法

    • 从「存储」角度,把session集中存储, 比如存储到redis或数据库里; 或者不同机器间同步数据, 比如tomcat session同步; 集中存储到redis是最常见的方案;
    • 从「分布」角度,让相同IP的请求在负载均衡时都打到同一台机器上。比如nginx配置ip_hash;
    • 不使用session, 服务无状态化, 在微服务里比较流行;

    spring session

    资料

    官方文档:
    Spring Session

    源码:
    spring-projects/spring-session: Spring Session

    大量示例:
    Spring Session

    上手

    文档:
    Spring Session - Spring Boot

    示例代码:
    https://gitee.com/qiaoxingxing/spring-security-learn/tree/master/spring-session-learn

    依赖:
    文档里少了lettuce-core的依赖, 报错:

    No session repository could be auto-configured, check your configuration (session store type is 'redis')

    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>io.lettuce</groupId>
        <artifactId>lettuce-core</artifactId>
        <version>6.1.4.RELEASE</version>
    </dependency>
    

    配置:

    spring:
      session:
        store-type: redis
    
      redis:
        host: localhost
        port: 6379
    

    其他配置:

    server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds is used.
    spring.session.redis.flush-mode=on_save # Sessions flush mode.
    spring.session.redis.namespace=spring:session # Namespace for keys used to store sessions.
    

    环境准备

    # 启动redis
    docker run -d --rm --name redis-test -p 6379:6379 redis
    

    nginx配置:

    upstream myapp1 {
        # ip_hash;
        server host.docker.internal:18080;
        server host.docker.internal:18081;   
    }
    
    server {
        listen 28080;
        location / {
            proxy_pass http://myapp1;
        }
    }
    

    启动nginx:

    PWD=$(pwd -W)
    docker container run -it -p 28080:28080 --rm --name mynginx 
      --volume "${PWD}/conf/default-balance.conf":/etc/nginx/conf.d/default.conf 
      nginx
    

    启动两个实例:

    mvn spring-boot:run -Dspring-boot.run.arguments=--server.port=18080
    mvn spring-boot:run -Dspring-boot.run.arguments=--server.port=18081
    

    测试

    spring.session.store-type: none时, sessionid一直在变, 设置session无法使用;
    设置为spring.session.store-type: redis, 程序正常;

  • 相关阅读:
    收集的java面试题
    重载和重写的区别
    java中封装的概念
    java中多态的概念
    vue中的$on,$emit,$once,$off源码实现
    js bind的实现
    对象的深拷贝
    v-for的简单实现
    v-for的显示过滤/排序结果
    ES6的数组方法之Array.from
  • 原文地址:https://www.cnblogs.com/QIAOXINGXING001/p/15434706.html
Copyright © 2020-2023  润新知