万万没想到 Spring Boot 一个依赖就能搞定 session 共享,简直太绝了!

1 篇文章 0 订阅
1 篇文章 0 订阅

在传统的单服务架构中,一般来说,只有一个服务器,那么不存在 Session 共享问题,但是在分布式/集群项目中,Session 共享则是一个必须面对的问题,先看一个简单的架构图:

如上图,是一个非常传统的服务端拓扑结构,一个 web 请求,经过 nginx 负载均衡后,转发到不同的服务器上去处理。那么来自同一用户的请求将有可能被负载分发到不同的实例中去,如何保证不同实例间 Session 共享成为一个不得不解决的问题。

简单点来说:例如客户端发起一个请求,这个请求到达 Nginx 上之后,被 Nginx 转发到 server 1 上,然后在 server 1 上往 session 中保存了一份数据,下次又来一个请求,这个请求被转发到 server 2 上,此时再去 Session 中获取数据,发现没有之前的数据。对于这一类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是 Redis

解决的示意图如下:

当所有服务器需要往 Session 中写数据时,都往 Redis 中写,当所有服务器需要读数据时,都从 Redis 中读。这样,不同的服务就可以使用相同的 Session 数据了。

这样的方案,可以由开发者手动实现,即手动往 Redis 中存储数据,手动从 Redis 中读取数据,相当于使用一些 Redis 客户端工具来实现这样的功能,毫无疑问手动实现工作量还是蛮大的。

一个简化的方案就是使用 Spring Session 来实现这一功能,Spring Session 就是使用 Spring 中的代理过滤器,将所有的 Session 操作拦截下来,自动的将数据同步到 Redis 中,或者自动的从 Redis 中读取数据。
Spring Session 作为 Spring 社区官方推荐的一个比较简单快速的 Java Web 分布式 session 解决方案,帮我们搞定了长期以来比较蛋疼的 session 分布式的问题。

对于开发者来说,所有关于 Session 同步的操作都是透明的,开发者使用 Spring Session,一旦配置完成后,具体的用法就像使用一个普通的 Session 一样。

前面是枯燥的理论掰扯,接下来话不多说,开干!操作灰常简单!

创建一个 spinngboot 工程

引入 Web、Spring Session、Spring Security 以及 Redis依赖:

pox.xml 文件如下:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

这里我使用的 Spring Boot版本是 2.4.2,当使用版本高于Spring Boot2.1.5的时,除了上面这些依赖之外,还需要额外添加 Spring Security依赖(其他操作不受影响,仅仅只是多了一个依赖,当然也多了Spring Security的一些默认认证流程)。

application.properties配置

操作代码示例

配置完成后 ,就可以使用 Spring Session 了,其实就是使用普通的 HttpSession ,其他的 Session 同步到 Redis 等操作,框架已经自动帮你完成了!

考虑到一会 Spring Boot 将以多服务集群的方式启动 ,为了获取每一个请求到底是哪一个 Spring Boot提供的服务,需要在每次请求时返回当前服务的端口号,因此这里我注入了 server.port 。

然后进行项目打包:

启动redis

打包和启动redis都成功之后,启动项目的两个实例


然后在浏览器中访问 http://localhost:8080/set ,这时浏览器会自动跳转到如下界面,这是因为我们使用的springboot版本较高,加之引用了Spring Security依赖,所以会有这个界面蹦出来让我们进行安全验证。

输入usr用户,当访问http://localhost:8080/set后,你启动的8080服务的控制台会有密码运行出来,点击复制到这里登录即可。

登录成功后,会跳转到你真正要访问的界面。这时已经向 8080 这个服务的 Session 中保存一个变量,访问完成后,数据就已经自动同步到 Redis中了。

然后,再调用 http://localhost:8080/get 接口,就可以获取到 8080 服务的 session 中的数据:


此时关于 session 共享的配置就已经全部完成了,session 共享的效果我们已经看到了,但是每次访问都是我自己手动切换服务实例,因此,接下来我们来引入 Nginx ,实现服务实例自动切换。

启动Nginx

很简单,进入 Nginx 的安装目录的 conf 目录下(默认是在 /usr/local/nginx/conf),编辑 nginx.conf 文件

默认配置是这样子的:

我们改成如下图配置:


然后执行重启nginx

在这段配置中:

upstream 表示配置上游服务器
javaboy.org 表示服务器集群的名字,这个可以随意取名字
upstream 里边配置的是一个个的单独服务
weight 表示服务的权重,意味者将有多少比例的请求从 Nginx 上转发到该服务上
location 中的 proxy_pass 表示请求转发的地址,/ 表示拦截到所有的请求,转发转发到刚刚配置好的服务集群中
proxy_redirect 表示设置当发生重定向请求时,nginx 自动修正响应头数据(默认是 Tomcat 返回重定向,此时重定向的地址是 Tomcat 的地址,我们需要将之修改使之成为 Nginx 的地址)。

配置完成后,将本地 Spring Boot 打包好的 jar 上传到 Linux

然后在 Linux 上分别启动两个 Spring Boot 实例:

nohup java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8080 >8080.log &
nohup java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8081 >8081.log &
  • nohup 表示当终端关闭时,Spring Boot 不要停止运行
  • & 表示让 Spring Boot 在后台启动
  • 8080.log表示日志文件输出到这里

Nginx 启动成功后,我们首先手动清除 Redis 上的数据,然后访问 192.168.66.128/set 表示向 session 中保存数据,这个请求首先会到达 Nginx 上,再由 Nginx 转发给某一个 Spring Boot 实例


如上,表示端口为 8081 的 Spring Boot 处理了这个 /set 请求,再访问 /get 请求:

可以看到,/get 请求是被端口为 8080 的服务所处理的。

当你再次刷新请求时,nginx按照你配置的权重比例转发分配到相应的服务中。

至此,实操完毕,是不是很简单呀!SpringBoot的强大之处就是避免重复造轮子,希望小伙伴们认真学习其中的奥妙所在。
在这里插入图片描述

原创不易,喜欢就关注吧。最好加个星标,这样精彩内容就不容错过啦!在这里你将收获爱与希望,更重要的是能学到小白程序员也能看懂的技术哦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要使用Redis实现Spring Boot应用程序的会话共享,您需要执行以下步骤: 1. 添加Redis依赖项 在您的Spring Boot项目中添加spring-boot-starter-data-redis依赖项,这将为您提供Redis客户端和Spring Session依赖项。 2. 配置Redis 在application.properties文件中添加Redis配置,包括Redis服务器的主机名、端口和密码。 3. 启用Spring SessionSpring Boot应用程序中启用Spring Session,您需要将@EnabaleRedisHttpSession注释添加到Spring Boot主应用程序类上。 4. 配置会话超时 您可以在application.properties文件中设置会话超时时间,例如:spring.session.timeout=30m。 5. 测试 最后,您可以测试您的Spring Boot应用程序是否正在使用Redis进行会话共享,通过多个实例运行应用程序,并在每个实例中访问同一URL并查看结果是否相同。 通过这些步骤,您应该能够在Spring Boot应用程序中使用Redis进行会话共享。 ### 回答2: 在Spring Boot中使用Redis实现session共享可以通过以下步骤实现: 1. 首先,确保在pom.xml文件中添加以下依赖项以在Spring Boot中使用Redis: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 在application.properties文件中配置Redis连接信息: ```properties spring.redis.host=your-redis-host spring.redis.port=your-redis-port spring.redis.password=your-redis-password ``` 3. 创建一个配置类(如RedisConfig.java),用于配置与Redis的连接以及序列化的设置: ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; @Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400) // 设置session的有效时间,单位为秒 public class RedisConfig { @Bean public RedisSerializer<Object> redisSerializer() { // 使用JSON序列化器,存储到Redis中的Session以JSON格式保存,方便阅读 return new GenericJackson2JsonRedisSerializer(); } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); // 设置key和value的序列化器 template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(redisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(redisSerializer()); return template; } } ``` 4. 在需要使用session的地方注入`HttpSession`,并使用它来获取、设置和删除session中的属性: ```java import javax.servlet.http.HttpSession; // 注入HttpSession @Autowired private HttpSession session; // 获取session中的属性 Object attributeValue = session.getAttribute("attributeName"); // 设置session中的属性 session.setAttribute("attributeName", attributeValue); // 删除session中的属性 session.removeAttribute("attributeName"); ``` 这样,通过以上步骤,就可以在Spring Boot中使用Redis实现session共享了。注意,由于Redis是内存数据库,需要设置session的有效时间以避免占用过多的内存资源。 ### 回答3: 使用Spring Boot实现Session共享的方法有两种:使用Spring Session和使用RedisTemplate。 第一种方法是使用Spring Session来实现Session共享Spring Session一个用于在分布式环境下管理SessionSpring项目,它提供了一种基于SpringSession管理解决方案。要使用Spring Session,需要在pom.xml文件中添加相关依赖,然后在Spring Boot配置类中加上@EnableRedisHttpSession注解,配置Redis连接信息。这样,Spring Session会将Session信息存储到Redis中,实现了Session共享。 第二种方法是使用RedisTemplate来实现Session共享RedisTemplate是Spring Data Redis提供的一个用于操作Redis的模板类,可以方便地进行Redis的读写操作。要使用RedisTemplate实现Session共享,首先需要在pom.xml文件中添加相关依赖,然后在Spring Boot配置类中创建一个RedisConnectionFactory实例,并将其注入到RedisTemplate中。通过RedisTemplate,可以将Session信息存储到Redis中,并实现Session共享。 无论是使用Spring Session还是使用RedisTemplate,都需要在Spring Boot配置文件中配置Redis连接信息,包括Redis服务器的IP地址、端口号和密码(如果有)。此外,还可以配置Redis的连接池参数,以提高性能和并发能力。 总结起来,要使用Spring Boot实现RedisSession共享,可以使用Spring SessionRedisTemplate两种方式。通过配置相关依赖和连接信息,将Session信息存储到Redis中,实现Session共享。这样,在分布式环境下,不同的应用实例之间就能够共享Session,并实现会话的跨应用访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值