聊聊几种常见的分布式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,一经查实,立即删除!

相关文章

常见的几种编码方式

常见的编码方式及其特点&#xff1a; 编码方式的设计是为了适应不同的字符集和应用需求&#xff0c;因此它们在表示字符时使用的位数和字节数各不相同 常见编码方式及其位数和字节数 ASCII&#xff08;American Standard Code for Information Interchange&#xff09;&#x…

C#语言进阶(二)—事件 第三篇(事件访问器)

总目录 C# 语法总目录 系列链接 C#语言进阶(二) 事件 第一篇(发布订阅模式) C#语言进阶(二) 事件 第二篇(.net标准事件模型) C#语言进阶(二) 事件 第二篇(事件访问器) 事件 第三篇目录 事件 第三篇3. 事件访问器 事件 第三篇 3. 事件访问器 默认情况下&#xff0c;编…

【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中创…

spdlog日志库源码:全局管理类registry

概述 已经有了用于接收前端用户log消息的类logger&#xff0c;代表log消息的类是log_msg&#xff0c;后端写log消息到目标文件的类sink&#xff0c;格式化log消息为最终字符串的类formatter&#xff0c;解析pattern flag的类pattern_formatter等等。 每次使用时&#xff0c;可…

Forth Python语言:深度解析其四维、五维、六维与七维之奥秘

Forth Python语言&#xff1a;深度解析其四维、五维、六维与七维之奥秘 在编程语言的浩瀚星空中&#xff0c;Forth Python以其独特的魅力与深邃的内涵&#xff0c;吸引着众多探索者的目光。然而&#xff0c;这门语言究竟有何独到之处&#xff1f;本文将从四维、五维、六维和七…

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

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

Flutter 中的 CupertinoSliverNavigationBar 小部件:全面指南

Flutter 中的 CupertinoSliverNavigationBar 小部件&#xff1a;全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架&#xff0c;它允许开发者使用 Dart 语言来构建高性能、美观的移动、Web 和桌面应用。在 Flutter 的丰富组件库中&#xff0c;CupertinoSliverNavigation…

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

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

Apache Calcite - 自定义数据源适配之访问内存列表

前言 上一篇文章中学习了Calcite基本概念&#xff0c;其中框架的核心能力是通过统一的Sql访问不同来源的数据。这篇文章中将通过一个简单的例子学习如何实现改功能。 最终通过sql来访问Java List中的数据。 准备工作 maven依赖 <dependency><groupId>org.apache…

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

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

域名更换服务器的原因

在互联网的运营过程中&#xff0c;域名更换服务器是一个常见的操作&#xff0c;可能是由于业务扩展、性能需求、成本考虑或服务质量等多种因素。然而&#xff0c;这个过程如果处理不当&#xff0c;可能会导致网站访问中断、搜索引擎排名下降或用户体验受损。本文将探讨在域名更…

系统架构设计师【第11章】: 未来信息综合技术 (核心总结)

文章目录 11.1 信息物理系统技术概述11.1.1 信息物理系统的概念11.1.2 CPS的实现11.1.3 信息物理系统的建设和应用 11.2 人工智能技术概述11.2.1 人工智能的概念11.2.2 人工智能的发展历程11.2.3 人工智能关键技术 11.3 机器人技术概述11.3.1 机器人的概念11.3.2 机…

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

不管你是在上班&#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…