[分布式]分布式会话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, 程序正常;

posted @ 2021-10-21 18:54  QIAOXINGXING001  阅读(118)  评论(0编辑  收藏  举报