使用redis实现session共享

article/2025/9/17 10:09:52
继上一遍文章,使用nginx实现负载均衡以后,新的问题又产生了,当使用负载均衡以后,我们如何实现session共享,因为session是保存在服务端的,对于单体应用来说这不是问题,因为只有一个服务器,但是在多个服务器的情况下,我们在A服务器登陆成功,session存在A服务器,下一次请求被转发到了B,但是B服务器中没有对应的用户信息,重新让用户登录肯定不合适,这个时候我们需要将该session信息放在一个公共的地方,不管后续请求被转发到了哪个服务器,我们都去从公共的位置去取,这样就实现了session共享(类似问题的解决方案有很多,比如存入数据库、配置tomcat实现session同步,使用jwt等等),今天我们使用的是spring session+redis来实现.

此处的代码基于上一篇的nginx实现负载均衡
改造而来。
1.pom文件引入相关依赖(这是我全部的依赖,贴出来方便复制粘贴)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.1</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.weige</groupId><artifactId>test-db-nginx</artifactId><version>0.0.1-SNAPSHOT</version><name>test-db-nginx</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.1</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.6.4</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis --><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId><version>2.6.3</version></dependency></dependencies><build><finalName>bookTest86</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

2.配置redis相关信息

spring.redis.host=127.0.0.1
spring.redis.port=6380
spring.redis.password=123456

3.添加一个配置类

package com.weige.config;import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;/*** Created with IntelliJ IDEA.** @Author: weige* @Date: 2022/07/13/19:41* @Description:*/
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 70)//session过期时间,单位为秒
public class RedisSessionConfig {}

4.添加一个模拟用户登录/注销的接口

package com.weige.controller;import com.weige.entity.User;
import com.weige.vo.RespBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;/*** Created with IntelliJ IDEA.** @Author: weige* @Date: 2022/07/13/7:59* @Description:*/
@RestController
public class UserController {@Value("${server.port}")private  String port;//登录@PostMapping("/login")public RespBean login( HttpServletRequest request){HttpSession session=request.getSession();//获取当前的sessionIdString sessionId = session.getId();//懒得传入,在这里写死的,能说明问题就行User user=new User();user.setUsername("悟空");user.setPassword("123456");user.setAddress("北京市天安门");System.out.println("登陆成功,sessionId:"+sessionId+";user===>"+user);session.setAttribute(sessionId,user);return RespBean.ok("登陆成功:"+port,user);}//获取当前用户@GetMapping("/getuser")public RespBean getuser(HttpServletRequest request){HttpSession session=request.getSession();String sessionId = session.getId();System.out.println("获取用户,sessionId==>"+sessionId);return RespBean.ok("登陆成功:"+port,session.getAttribute(sessionId));}//注销@GetMapping("/logout")public RespBean loginout(String username, HttpServletRequest request){HttpSession session=request.getSession();//这里不做查询,直接清除sessionString sessionId = session.getId();System.out.println("注销登录,sessionId==>"+sessionId+"服务端口:"+port);session.removeAttribute(sessionId);return RespBean.ok("注销成功:"+port);}
}

5.改造获取数据的接口,添加了对用户是否登录的判断

package com.weige.controller;import com.weige.entity.Book;
import com.weige.entity.User;
import com.weige.service.BookService;
import com.weige.vo.RespBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;/*** Created with IntelliJ IDEA.** @Author: weige* @Date: 2022/07/11/20:57* @Description:*/
@RestController
@RequestMapping("/book")
public class BookController {@AutowiredBookService bookService;@Value("${server.port}")private  String port;@GetMapping("/")public RespBean getAllBooks(HttpSession session){//HttpSession session=request.getSession();String sessionId = session.getId();System.out.println("查询book,sessionId==>"+sessionId+"服务端口:"+port);User user= ((User) session.getAttribute(sessionId));if(user==null){return RespBean.error("用户还没登录,请先登录!服务端口:"+port);}System.out.println("我从session中拿到了User--->"+user );List<Book> books=bookService.getAllBooks();return RespBean.ok(port,books);}@PostMapping("/")public RespBean addBook(@RequestBody Book book){int ret=bookService.addBook(book);return RespBean.ok(port,ret);}@PutMapping("/")public RespBean updateBook(@RequestBody Book book){int ret=bookService.updateBook(book);return RespBean.ok(port,ret);}@DeleteMapping("/{id}")public RespBean delBook(@PathVariable Integer id){int ret=bookService.delBook(id);return RespBean.ok(port,ret);}
}
关键的信息就是这些,在获取全部book信息的时候,会根据sessionId,从当前session中获取用户信息,如果用户不存在,就提示没有登录,登录后可以正常获取,我们将项目打包,放在服务器上,以8886和8887端口启动,结合之前配置的nginx负载均衡,我们希望无论在那一台服务上登录过,都可以正常的获取book信息,这样我们session共享的需求就实现了

(1)启动8886
在这里插入图片描述
(2)启动8887
在这里插入图片描述
(3)请求获取book接口,提示未登录,此时提供服务的是8886
在这里插入图片描述
(4)请求登录接口,注意此时提供服务的是8887,多次请求,8886和8887会交替出现,这是因为我们在nginx中配置的权重
在这里插入图片描述
(5)再次请求获取book接口(此时提供服务的是8886)
在这里插入图片描述
以上说明,同一个session,我们从任意一台服务器登陆成功后,在其它服务器上都可以获取到session中的用户信息,实现了session共享。


http://chatgpt.dhexx.cn/article/N3QMgL3r.shtml

相关文章

Session共享问题-session原理

问题1&#xff1a;微服务情况下。域名不同。session不共享 问题2&#xff1a;分布式系统下。同一个域名下&#xff0c;多个服务。session会出现不同步问题&#xff08;例如第一次访问的是A服务&#xff0c;保存了。第二次访问了B,查询到的还是没信息&#xff09; 解决&#xf…

Springboot:Session共享

1、概述 传统单机web应用中&#xff0c;一般使用tomcat/jetty等web容器时&#xff0c;用户的session都是由容器管理。浏览器使用cookie中记录sessionId&#xff0c;容器根据sessionId判断用户是否存在会话session。这里的限制是&#xff0c;session存储在web容器中&#xff0c…

Java -- SpringSession实现session共享

在集群系统中&#xff0c;经常需要将 Session 进行共享。不然会出问题&#xff1a;用户在系统A上登陆以后&#xff0c;假如后续的一些操作被负载均衡到系统B上面&#xff0c;系统B发现本机上没有这个用户的 Session &#xff0c;会强制让用户重新登陆。 如在同域名&#xff0c…

shiro分布式session共享

当我们开发的程序需要跑在多个tomcat容器或者多台机器上时&#xff0c;shiro的默认session存储就不能满足我们的需求了&#xff0c;其中shiro默认的session是存储在运行jvm内存中的&#xff0c;使用的AbstractSessionDAO抽象类的一个子类MemorySessionDAO&#xff0c;当我们需要…

tomcat+redis实现session共享

注意&#xff1a;在实际应用中&#xff0c;发现该方案会不定期导致Tomcat假死&#xff08;怀疑Redis连接未释放&#xff09;&#xff0c;慎用。 服务器192.168.14.132和192.168.14.133&#xff0c; 均已经安装tomcat&#xff0c;tomcat安装过程不再赘述。 采用192.168.14.132…

Session共享问题

Session共享及Session保持或者叫做Session⼀致性 1、Session问题原因分析 出现这个问题的原因&#xff0c;从根本上来说是因为Http协议是无状态的协议。客户端和服务端在某次会话中产生的数据不会被保留下来&#xff0c;所以第⼆次请求服务端无法认识到你曾经来过&#xff0c;…

session共享(redis实现)

引言 大厂很多项目都是部署到多台服务器上&#xff0c;这些服务器在各个地区都存在&#xff0c;当我们访问服务时虽然执行的是同一个服务&#xff0c;但是可能是不同服务器运行的&#xff1b; 在我学习项目时遇到这样一个登录情景&#xff0c;假设有如下三台服务器&#xff0…

如何实现session共享的几种解决方案?

先了解一下为什么会出现这种session共享的解决方案&#xff1f; 随着互联网公司的项目在微服务和分布式的环境下进行的搭建&#xff0c;导致一个项目可能分别部署在几个甚至很多的服务器集群下&#xff0c;此时就会出现一个问题当用户进行一个session会话的时候&#xff0c;比…

session共享几种方式

Session共享三种方式 1.nginx基于ip_hash负载均衡。 只需要更改nginx.conf配置文件。添加ip_hash就可以了。 缺点&#xff1a;1.由于ip_hash分配tomcat的时候用的是除法&#xff0c;所以新添加一台服务器会导致分配不到原来程序上&#xff0c;session会丢失。2.同一个公网ip…

session共享学习

一、Session共享 1 什么是Session共享    是指在一个浏览器对应多个Web服务时&#xff0c;服务端的Session数据需要共享。 2 Session共享应用场景 单点登录Web服务器集群等 3 Session共享常见的解决方案 3.1 Session复制       通过对应用服务器的配置开启服务器的Sess…

redis实现session共享

session共享 什么是session&#xff1f; 由于 HTTP 协议是无状态的协议&#xff0c;所以服务端需要记录用户的状态时&#xff0c;就需要用某种机制来识具体的用户。Session 是另一种记录客户状态的机制&#xff0c;不同的是 Cookie 保存在客户端浏览器中&#xff0c;而 Sessi…

UART协议概述与实现

UART协议概述&#xff08;一&#xff09; 协议描述关键代码逻辑写在最后 协议描述 常见的三大低速通信协议之一&#xff0c;UART&#xff0c;通用异步收发协议。非常简单的协议&#xff0c;协议细节不需要多说&#xff0c;只说需要注意的点。空闲位为高位&#xff0c;起始位为…

UART协议简述及编程

UART原理简述 通用异步收发器简称UART&#xff08;universal asynchronous receiver transmitter&#xff09;。他的用途很广泛&#xff0c;一般常用的就是用来输出打印的信息&#xff0c;也可以外接各种模块&#xff0c;例如GPS和蓝牙等。 正是因为这种协议非常的简单可靠&…

UART协议及串口回环

UART协议及串口回环 一、异步通信的分类1、UART&#xff08;通用异步收发器&#xff09;2、RS4223、RS4854、Modbus5、接口标准 二、UART协议要求1、空闲状态2、起始位3、数据位4、校验位5、停止位6、波特率7、比特率 三、汉字发送四、串口回环uart_txuart_rxctrltop 五、参考六…

基于verilog的uart协议实现

目录 1、理论介绍 2、架构设计 3、代码设计 一、发送模块代码 二、接收代码设计 三、顶层模块设计 四、测试代码 4、仿真实验 1、理论介绍 uart&#xff1a;通用异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter)&#xff0c;是一种串行的收发方式…

UART协议快速扫盲(图文并茂+超详细)

文章目录 1 UART发展历史1.1 早期的串行通讯设备1.2 早期的芯片级UART1.3 现代UART的发展 2 预备知识3 协议层起始位数据校验位停止位波特率 4 传输过程5 物理层6 优缺点 1 UART发展历史 1.1 早期的串行通讯设备 早期的电报机器使用长度可变的脉冲信号进行数据传输&#xff0…

UART协议学习

通信协议分层 物理层 物理层规定通讯系统具有的机械、电子功能部分的特性&#xff0c;确保原始数据在物理媒体的传输。如RS232、RS485等就是电气协议&#xff0c;规定了数据传输时的电平标准&#xff0c;网络上许多博主将UART看作一个协议族&#xff0c;这些电气协议都是UART…

c语言模拟uart协议的收发

这篇文章注重思想的讲解,理解下来肯定对uart协议有一个更深的认识。 uart协议,通常用在嵌入式设备之间的通信。像下面这样: 问题一:uart是全双工还是半双工? 你完全可以将两个设备想象成两个人,上图中的两条线想象成A和B的对话。A对B说话和B对A说话的一个场景。问大家一个问题…

UART协议详解

通用异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter)&#xff0c;通常称作UART。 定义&#xff1a;UART是一种通用串行数据总线&#xff0c;用于异步通信。该总线双向通信&#xff0c;可以实现全双工传输和接收。在嵌入式设计中&#xff0c;UART用于主…

Linux·UART协议

目录 一、什么是UART&#xff1f; 二、UART的帧格式 2.1 为什么UART的传输需要起始位&#xff1f; 2.2 UART基本的数据形式 2.3 为什么UART的数据位可变&#xff1f; 三、UART的波特率 3.1 什么是波特率 3.2 如何换算波特率 3.3 波特率和采样频率是一样的吗&#xff1f…