3

SpringSession:集群和微服务的会话共享方案(HttpSession+Reids)

 2 years ago
source link: https://maxqiu.com/article/detail/106
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
SpringSession:集群和微服务的会话共享方案(HttpSession+Reids)
SpringSession:集群和微服务的会话共享方案(HttpSession+Reids)

2021/07/29  Java  Redis  SpringBoot

示例代码:
GitHub:https://github.com/Max-Qiu/demo-SpringBoot
Gitee:https://gitee.com/Max-Qiu/demo-SpringBoot


官方文档:https://spring.io/projects/spring-session

Spring Session提供了一个API和实现来管理用户的会话信息,同时也使支持集群会话变得简单,而无需绑定到应用程序容器特定的解决方案。

SpringSession集成了如下环境

  • HttpSession:常用的SpringMVC模式,例如Tomcat。
  • WebSocket:WebSocket
  • WebSession :Spring WebFlux模式

存储Session的数据源有如下方案

  • Reids
  • JDBC
  • MongoDB
  • geode

本文以HttpSession+Reids为例

Maven依赖

  1. <!-- Web -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <!-- SpringSession Redis 数据源 -->
  7. <dependency>
  8. <groupId>org.springframework.session</groupId>
  9. <artifactId>spring-session-data-redis</artifactId>
  10. </dependency>
  11. <!-- Redis -->
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-data-redis</artifactId>
  15. </dependency>
  16. <!-- 连接池依赖 -->
  17. <dependency>
  18. <groupId>org.apache.commons</groupId>
  19. <artifactId>commons-pool2</artifactId>
  20. </dependency>

yml配置

主要配置一个store-type,Redis相关配置建议参考SpringBoot2.4.x整合Redis

  1. server:
  2. port: 8080
  3. spring:
  4. session:
  5. store-type: redis # 使用 Redis 存储 Session
  6. #redis:
  7. # flush-mode: immediate # 会话刷新模式(此处有bug,设置无效,需要在启动类注册上设置)
  8. # namespace: demo::session # 用于存储会话的键的命名空间(此处有bug,设置无效,需要在启动类注册上设置)
  9. # Redis连接相关配置
  10. redis:
  11. host: redis # 地址
  12. port: 6379 # 端口
  13. username: # 用户名
  14. password: 123 # 密码
  15. database: 0 # 指定数据库序号
  16. ssl: false # 是否启用SSL
  17. connect-timeout: 1000 # 连接超时时间(毫秒)
  18. timeout: 1000 # 操作超时时间(毫秒)
  19. client-name: # 客户端名称(不知道干嘛用的)
  20. client-type: lettuce # 驱动类型
  21. # 连接池配置
  22. lettuce:
  23. pool:
  24. min-idle: 1 # 最小空闲连接(默认0)
  25. max-idle: 8 # 最大空闲连接(默认8)
  26. max-active: 16 # 最大连接数(默认8,使用负值表示没有限制)
  27. max-wait: -1ms # 最大阻塞等待时间(默认-1,负数表示没限制)

Application配置

需要在启动类添加@EnableRedisHttpSession注解,相关设置也要在该注解内设置,yml内的配置无效,应该是bug

  1. @EnableRedisHttpSession(
  2. // 设置存储会话的键的命名空间
  3. redisNamespace = "demo::session",
  4. // 设置会话超时时间
  5. maxInactiveIntervalInSeconds = 600,
  6. // Redis会话的刷新模式。
  7. // ON_SAVE:(默认值)仅在调用SessionRepository.SAVE(Session)时更新备份Redis。在web环境中,发生在HTTP响应提交之前。
  8. // IMMEDIATE:会话的任何更新都会立即写入Redis实例
  9. flushMode = FlushMode.IMMEDIATE)
  10. @SpringBootApplication
  11. public class SpringSessionApplication {
  12. public static void main(String[] args) {
  13. SpringApplication.run(SpringSessionApplication.class, args);
  14. }
  15. }

Config配置

Redis序列化设置

注意:该序列化仅针对Session的序列化,与RedisTemplate的设置不通用

  1. /**
  2. * Redis共享会话的序列化设置
  3. */
  4. @Configuration
  5. public class RedisSessionConfig {
  6. /**
  7. * 使用 fastjson 序列号
  8. */
  9. @Bean
  10. public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
  11. return new GenericJackson2JsonRedisSerializer();
  12. }
  13. }

浏览器Cookie设置

  1. /**
  2. * SpringSession的Cookie配置
  3. */
  4. @Configuration
  5. public class RedisCookieConfig {
  6. /**
  7. * 设置Cookie序列化的配置
  8. */
  9. @Bean
  10. public CookieSerializer cookieSerializer() {
  11. DefaultCookieSerializer serializer = new DefaultCookieSerializer();
  12. // Session的key,默认:SESSION
  13. serializer.setCookieName("SESSION");
  14. // Session的value是否进行Base64编码,推荐关闭,方便浏览器内查看到value值
  15. serializer.setUseBase64Encoding(false);
  16. // Session的路径
  17. serializer.setCookiePath("/");
  18. // Session的可读域名(默认当前域名)若需要多域名共享Cookie,则需要设置为主域名
  19. // serializer.setDomainName("demo.com");
  20. return serializer;
  21. }
  22. }

推荐阅读:

Session读写示例

  1. /**
  2. * Session读写
  3. *
  4. * @author Max_Qiu
  5. */
  6. @RestController
  7. public class IndexController {
  8. @Value("${server.port}")
  9. private String port;
  10. @RequestMapping("get")
  11. public String get(HttpSession session) {
  12. String name = (String)session.getAttribute("name");
  13. return "port:" + port + "\tname:" + (name != null ? name : "null");
  14. }
  15. @RequestMapping("set")
  16. public String set(HttpSession session) {
  17. session.setAttribute("name", "max");
  18. return "ok";
  19. }
  20. }

多服务示例(集群和微服务)

  1. 启动服务,再使用--server.port=8081启动第二个服务
  2. 本地Nginx配置如下,并启动Nginx服务

    1. upstream demo{
    2. server 127.0.0.1:8080;
    3. server 127.0.0.1:8081;
    4. }
    5. server {
    6. listen 80;
    7. location / {
    8. proxy_pass http://demo/;
    9. add_header Strict-Transport-Security "max-age=31536000";
    10. proxy_set_header X-Real-IP $remote_addr;
    11. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    12. proxy_set_header Host $http_host;
    13. proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr;
    14. proxy_set_header X-Forwarded-Proto $scheme;
    15. proxy_redirect default;
    16. }
    17. }
  3. 访问http://127.0.0.1/set写Session
  4. 访问http://127.0.0.1/get读Session,并且多次访问可以看到不同服务均可以读取Session中的值

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK