聊聊几种常见的分布式Session解决方案


highlight: xcode

theme: vuepress

问题引入:什么是分布式Session?

分布式 Session 是指在多台服务器之间共享和管理用户的会话数据,使得用户的会话状态能够在不同的服务器上保持一致。这样,无论用户的请求被路由到哪台服务器,都能够访问到相同的会话信息,从而保证用户体验的一致性。

回顾一下单机服务的 HttpSession 的存储:

在传统的 JavaWeb 的 Tomcat + Servlet 的项目中,HttpSession 通常存储在 JVM 内存中。浏览器第一次访问服务之后,会得到一个名为 JSESSIONID 的 Cookie。在后续的请求中,浏览器都会携带此 Cookie。用一个图来简单说明一下:

image.png

在 HttpSession 中存储用户数据最原始的做法是怎么做的呢?初学者一般都是这么写(因为教科书上也是这么写的🐶):

java public void doGet(HttpServletRequest req, HttpServletResponse resp) { HttpSession session = req.getSession(); // 获取用户名 String username = req.getParameter("username"); session.setAttribute("username", username); // 后续操作... }

这种写法只适合单机部署的场景,在分布式场景下是不可行的,因为请求会到不同的机器上,每台机器上的数据都不一样。而且服务端对同一个客户端的请求不能共享 Session。

常见解决方案

对于分布式 Session,通常有以下几种解决方案:

  1. Session 粘滞:通过负载均衡器(如 Nginx、F5 等)将同一用户的请求始终路由到同一台服务器上。
  2. 数据库共享 Session:将 Session 存储在数据库中(如 MySQL、PostgreSQL 等),各个服务器访问同一个数据库。
  3. Token 方式:将 Session 数据编码为 Token(如 JWT),并由客户端保存(通常在 Cookie 或 HTTP 头中传输)。
  4. 分布式文件系统:将 Session 存储在分布式文件系统(如 NFS、GlusterFS 等)中,各个服务器访问共享的文件系统。
  5. 缓存共享 Session:使用分布式缓存系统(如 Redis、Memcached 等)存储 Session 数据,各个服务器共享同一个缓存。

Session 粘滞

以 nginx 的 IP Hash 策略为例,通过 IP Hash 策略可以将客户端的 IP 地址哈希到特定的后端服务器上,从而确保同一个客户端的请求总是被路由到同一台服务器上。

示例配置:

```conf http { upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; server backend3.example.com; }

server {location / {proxy_pass http://backend;}
}

} ```

寥寥几行,通过简单的配置即可实现。同一客户端的请求总是路由到同一台服务器,因此可以保证会话的一致性,避免 Session 丢失。

但是缺点也很明显,由于 IP 地址的分布不均匀,可能导致某些服务器负载过重,而其他服务器负载较轻。如果某台服务器宕机,与其绑定的所有客户端会话信息都会丢失,无法自动迁移到其他服务器。添加或移除服务器会改变 IP 到服务器的映射,导致会话丢失。对于跨地域的用户,IP Hash 可能导致某些地域的用户集中到特定的服务器,进一步加剧负载不均衡。

明显缺点大于优点,所以基本不推荐。

数据库共享Session

使用数据库存储 Session,虽然实现起来很简单,但是会导致每次请求都要查询数据库让数据库的负载变大。 在一些性能敏感的系统中,性能瓶颈明显,扩展性很差。所以也不推荐。

Token方式

将 Session 数据编码为 Token,并由客户端保存可以让服务端无状态化,扩展性好,不依赖集中存储。但是 Token 很可能被截取和伪造,安全性低,需要加密和签名。也不是很推荐。

分布式文件系统

使用分布式文件系统才存储 Session,实现起来相对简单,可以利用现有的文件系统。但是性能比较差,文件系统的同步和一致性问题需要考虑,所以也不是很推荐。

缓存共享Session

上面说了几种方案都不推荐,这个总得推荐了吧?哈哈哈,那肯定啊,不然这篇文章都没有写的必要了。

使用缓存系统存储 Session,读写速度快,而且支持高并发。需要注意的是缓存失效策略。以 Redis 为例存储分布式 Session。

创建一个 Spring Boot 工程,导入 Spring Session 的依赖:

```xml org.springframework.boot spring-boot-starter-web

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

```

配置一下 application.yml 文件:

```yaml server: port: 8081

spring: redis: port: 6379 host: localhost ```

写一个简单的 Controller:

```java @RestController public class TestController {

@GetMapping("/")
public String hello(HttpServletRequest req) {HttpSession session = req.getSession(true);System.out.println(session);Cookie[] cookies = req.getCookies();if (cookies == null) {return "Hello World";}for (Cookie cookie : cookies) {System.out.println(cookie.getName());}return "Hello World";
}

} ```

访问一下浏览器:

image.png

可以看到名称为 JSESSIONID 的 Cookie。

再看一下 Redis 中的数据:

image.png

可以看到 Session 数据已经自动存到 Redis 中了。你可能疑问为什么会自动存进去了,我并没有干什么操作啊?

因为 spring-session-data-redis 这个包在 Spring 接收到了请求的时候自动帮我们做了这个操作。有兴趣的话可以分析一下源码。

我们可以再开启一个实例观察一下 Cookie 是否发生了变化:

image.png

访问一下 http://localhost:8082 然后打开 F12 查看 Cookie:

image.png

可以看到 8081 和 8082 的 JSESSIONID 的 Cookie 是一样的,最终实现了 Session 的共享。

怎么样,你学会了吗?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/20269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Go语言精进之路】构建高效Go程序:掌握变量、常量声明法则与iota在枚举中的奥秘

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 引言一、变量1.1 基础知识1.2 包级变量的声明形式深入解析&#x1f4cc; 声明并同时显式初始化&#x1f4cc; 声明但延迟初始化&#x1f4cc; 声明聚类与就近原则 1.3 局部变量的声明形式深入探讨&#x1f4cc; 延迟初始化的…

你认识nginx吗,nginx是做什么的,nginx可以做什么 --1)nginx介绍

一.Nginx 介绍 Nginx&#xff08;发音同engine x&#xff09;是一个异步框架的 Web 服务器&#xff0c;也可以用作反向代理&#xff0c;负载平衡器 和 HTTP 缓存。该软件由 Igor Sysoev 创建&#xff0c;并于2004年首次公开发布。同名公司成立于2011年&#xff0c;以提供支持。…

PHP:集成Xunsearch生成前端搜索骨架

如果是安装宝塔&#xff0c;我们在集成xunsearch的时候就会比较简单&#xff0c;后面我们在介绍其他的接入方式&#xff1b; 首先我们进入到宝塔管理后台&#xff1a;【软件商店】-【输入xun】-【点击xunsearch】直接安装即可 安装成功之后&#xff0c;会自动在www/server中创…

大模型高级 RAG 检索策略:自动合并检索

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学. 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总合集&…

比较3维空间中4个点的不同结构

在4*4*4的3维空间中&#xff0c;取4个点共有635376种可能&#xff0c;有209个结构&#xff0c;继续按旋转对称分类则只有55个不同的结构。如其中的4t12 4个点在同一个平面&#xff0c;有1个点与其中的3个点不在同一行也不在同一列&#xff0c;这样的位置不止一个 这两个结构都是…

ubuntu系统下安装mysql的步骤详解

一、下载安装包 下载地址&#xff1a; https://dev.mysql.com/downloads/repo/apt 跳转到这个页面&#xff1a; 直接点击Download。 直接点击最下面的开始下载安装包即可。 二、将安装包下载到ubuntu系统中 先将用户切换成root用户&#xff0c;把下载好的安装包复制到桌面上&…

丛林生存法则其实就两个字:输出

不管你是在上班&#xff0c;还是在灵活就业&#xff0c;现在的大环境下&#xff0c;你要想活下来&#xff0c;生存下去&#xff0c;一定要记住这两个字&#xff1a;输出。如果你能记住更多的字&#xff0c;那便是持续高水平的输出。 你如果是大厂程序员&#xff0c;你肯定发现…

Linux DHCP server 配置

参考&#xff1a;linux dhcp配置多vlan ip_linux 接口vlan-CSDN博客 配置静态IP地址&#xff1a; 给固定的MAC地址分配指定的IP地址&#xff0c;固定的IP地址不必包含在指定的IP池中&#xff0c;如果包含在IP地址池中&#xff0c;固定的IP地址会从IP地址池中移除 配置方法&…

清洁力强的洗地机前十名排行榜:2024十大洗地机热销款式好用不踩雷

如今&#xff0c;洗地机行业竞争激烈&#xff0c;各品牌紧紧抓住用户对智能化和深度清洁的需求&#xff0c;深入研究创新。经过几轮行业内部的激烈竞争后&#xff0c;许多厂商在宣传中各说各的&#xff0c;对洗地机的重要参数描述不一&#xff0c;给消费者的选择带来了不少困惑…

【CVPR_2024】:逐元素乘积为什么会产生如此令人满意的结果?

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言论文重写星形运算一层网络推广多层网络特殊情况 W 1 W_1 W1​和/或 W 2 W_2 W2​…

JDK版本特性(JDK8\11\17\21版本)

JDK版本特性 Oracle官网https://www.oracle.com/java/technologies/java-se-support-roadmap.html Oracle官网中JDK版本的说明&#xff0c;Java SE 8、11、17和21是LTS版本。也就是长期支持版本。 我们针对这几个版本了解学习下对应版本的新特性。 JDK8版本 正式发布于2014…

Facebook的创新实验室:人工智能与新技术探索

Facebook作为全球领先的社交媒体平台之一&#xff0c;一直在不断探索和应用最新的技术来改善用户体验、推动创新和拓展业务边界。其创新实验室更是探索人工智能&#xff08;AI&#xff09;和新技术的前沿&#xff0c;为未来的社交媒体发展开辟了新的可能性。本文将深入探讨Face…

【题解 | 分享】2023年十四届蓝桥杯国赛(Java B组)

互质 答案&#xff1a;640720414 参考&#xff1a; public class Main {static int mod 1000000007;public static void main(String[] args) {long sum power(2023, 2023);long p1 ((sum % mod) * power( 7, mod - 2)) % mod;long p2 ((sum % mod) * power( 17, mod -…

【ZYNQ】SCU 与 GIC

在多 CPU 架构中&#xff0c;处理器之间可以对共享数据进行操作。Snoop control uint (SCU) 模块用于确保每个处理器都在最新的数据拷贝上运行&#xff0c;从而保持缓存一致性。通用中断控制器 Generic interrupt controller (GIC) 使用优先级的思想&#xff0c;管理 CPU 中断信…

Spring系统学习 - Spring入门

什么是Spring&#xff1f; Spring翻译过来就是春天的意思&#xff0c;字面意思&#xff0c;冠以Spring的意思就是想表示使用这个框架&#xff0c;代表程序员的春天来了&#xff0c;实际上就是让开发更加简单方便&#xff0c;实际上Spring确实做到了。 官网地址&#xff1a;ht…

【Mac】XMind for mac(XMind思维导图)v24.04.10311软件介绍和安装教程

软件介绍 XMind for Mac是一款功能强大的思维导图软件。它具有以下主要特点&#xff1a; 1.多样化的思维导图功能&#xff1a;XMind for Mac提供了丰富的思维导图编辑功能&#xff0c;用户可以创建各种类型的思维导图&#xff0c;包括组织结构图、逻辑图、时间轴图等&#xf…

fluent UI v9版本Dialog右上角x按钮聚焦问题解决

右上角x按钮聚焦效果展示 第一次点击不会聚焦&#xff0c;第二次或多次点击会出现这种情况。如果多个地方公用一个页面里&#xff0c;这个页面包含这个组件&#xff0c;那其它页面刚打开弹框就是聚焦状态&#xff0c;是个样式的问题。 解决&#xff1a; import * as React fr…

【Vue3】自定义组件directiveapp.use()

历史小剧场 崇祯很勤政&#xff0c;崇祯并非王国之君&#xff0c;弘光很昏庸&#xff0c;弘光活该倒霉&#xff0c;几百年来&#xff0c;我们都这样认为。 但我们之所以一直这样认为&#xff0c;只是因为有人这样告诉我们。 之所以有人这样告诉我们&#xff0c;是因为他们希望我…

比较与深浅克隆

1.比较 &#xff08;1&#xff09;Comparable接口&#xff1a;&#xff08;重写compareTo方法&#xff09; 由于它是一个接口&#xff0c;而且在这个接口中只有一个compareTo方法&#xff0c;所以所有实现该接口的类都需要重写。这个compareTo方法相当于制定一个比较标准&…

pyinstaller将py文件打包成exe

pyinstaller将py文件打包成exe 一、为什么需要将python文件打包成exe文件?二、具体操作步骤一、为什么需要将python文件打包成exe文件? python文件需要在python环境中运行,也就是需要安装python解释器。有时我们自己写的python程序需要分享给自己的朋友、同事或者合作伙伴,…