谷粒商城实战笔记-225~226-商城业务-认证服务-分布式session不共享不同步问题

文章目录

一,225-商城业务-认证服务-分布式session不共享不同步问题

1,首页无用户信息

谷粒商城首页,点击超链接您好,请登录,正常情况下应该跳转到Auth模块的login页面,登录成功后,会重定向到首页,超链接您好,请登录应该替换为用户名。

但是实际开发过程中出现了这样一个问题,登录成功后,超链接您好,请登录未被替换,再次点击这个超链接,不会跳转到登录界面,说明后台认为已经登录成功,直接重定向到首页了,但是首页没有拿到用户信息。

F12查看Application信息,也没有发现sessioncookie信息。

2,定位

梳理登录流程,看看问题可能出现在哪个环节。

  • 首页点击超链接您好,请登录
  • 跳转到auth.gulimall.com/login.html,这里很关键,商城用户认证模块的域名和首页域名不一致
  • 认证模块完成用户验证后,将用户信息保存在session
  • auth模块的前端页面login.htmlsession信息保存在cookie中,注意是保存在域名auth.gulimall.com
  • 重定向到首页,首页的域名是gulimall.com,所以不会携带cookie信息,首页后端拿不到用户信息,无法渲染页面

一句话解释问题原因 :登录功能是两个模块协同完成的,登录模块完成登录,在域名auth.gulimall.com下保存session首页模块的域名是gulimall.com,拿不到session,取不到用户信息。

下图可以看到auth.gulimall.com下是有cookie保存的。

3,谷粒商城session、cookie必须解决的两大问题

谷粒商城session、cookie必须解决的两大问题:

  • 1,auth.gulimall.com和gulimall.com的cookie信息不能共享;
  • 2,分布式服务间的session不能共享;

原因与原理:

  • 域名限制: Cookie 是基于 HTTP 协议中的 Set-Cookie 头来设置的。根据 HTTP 协议的规定,每个 Cookie 都有一个 Domain 属性,这个属性定义了该 Cookie 可以被哪些域名下的请求访问。如果一个 Cookie 设置为 .example.com,那么所有以 example.com 结尾的子域都可以访问这个 Cookie。

  • 子域名隔离: 在您的例子中,auth.gulimall.comgulimall.com 分别代表了不同的子域。默认情况下,浏览器不会在这些不同的子域间共享 Cookie。例如,如果 Cookie 的 Domain 属性设置为 auth.gulimall.com,则它只能被 auth.gulimall.com 访问,而不能被 gulimall.com 或其他子域访问。

  • SameSite 属性: 此外,现代浏览器还支持 SameSite 属性来进一步控制 Cookie 的行为。如果设置了 SameSite=StrictSameSite=Lax,那么即使 Cookie 的 Domain 属性允许跨子域访问,它们也不会被发送到第三方站点(即非第一方站点),这进一步限制了 Cookie 的共享能力。

3.2. 分布式服务间的 session 不能共享

原因与原理:

  • Session 存储位置: 在传统的单体应用中,Session 通常存储在服务器端,如内存或文件系统中。但是,在分布式环境中,用户请求可能被负载均衡器分发到不同的服务器上。这意味着,同一个用户的 Session 数据可能会被存储在不同的服务器上,导致无法直接访问。

  • 状态无感知: 分布式系统的每个服务实例都是独立运行的,并且为了提高可伸缩性和容错性,通常设计为无状态的。这意味着每个服务实例不应该依赖于其他实例的数据或状态。因此,直接共享 Session 数据会破坏这种设计原则。

  • 横向扩展: 在分布式系统中,服务实例可以动态地增加或减少。如果使用集中式的 Session 存储方案,例如内存中的 Map 或者文件,那么随着服务实例的增加,这种方案将不再适用,因为新的实例无法自动获取其他实例的 Session 信息。

二,226-商城业务-认证服务-分布式session解决方案原理

分布式session问题4种解决方案:

  • 1,服务间session复制
  • 2,客服端存储cookie,服务端无状态
  • 3,一致性hash,将ip相同的请求转发到相同服务器
  • 4,统一存储session,如用redis存储session

1. 服务间 Session 复制

具体实现:

  • 每个服务实例都维护一份完整的 Session 数据副本。
  • 当 Session 数据更新时,更新的信息会被同步到其他服务实例。

优点:

  • 实现简单,不需要额外的存储系统。
  • 快速响应客户端请求,无需额外的网络延迟。

缺点:

  • 每个服务实例都需要保存所有用户的 Session 数据,可能会消耗大量的内存资源。
  • 随着服务实例数量的增加,同步 Session 数据变得更加复杂,可能导致性能瓶颈。
  • 如果 Session 数据非常大,同步过程可能会变得缓慢,影响用户体验。

2. 客户端存储 Cookie,服务端无状态

具体实现:

  • 使用 Token 或者 Session ID 存储在客户端 Cookie 中。
  • 服务端每次请求时从 Cookie 中读取 Token 或 Session ID,并将其作为认证信息使用。
  • 服务端不保存任何 Session 数据,所有认证信息都存储在客户端 Cookie 中。

优点:

  • 服务端无状态,易于水平扩展。
  • 简化了后端服务的设计和部署。

缺点:

  • 安全性较低,因为敏感数据存储在客户端,容易被截获或篡改。
  • Cookie 的大小有限制(通常为 4KB),无法存储大量数据。
  • 不适合存储敏感信息,如用户密码或其他重要的安全凭证。

3. 一致性 Hash

具体实现:

  • 根据客户端 IP 地址或其他唯一标识符计算出一个哈希值。
  • 将这个哈希值映射到特定的服务实例上,确保来自同一客户端的请求总是被路由到同一台服务器。
  • 这样,每个客户端的 Session 数据就可以只在一台服务器上进行管理。

优点:

  • 减少了 Session 复制的需求,降低了内存消耗。
  • 通过负载均衡器实现,无需更改应用程序逻辑。

缺点:

  • 单点故障问题:如果负责某个客户端 Session 的服务器出现故障,该客户端的 Session 数据就会丢失。
  • 横向扩展问题:当添加或移除服务实例时,可能会导致重新分配客户端请求,从而影响 Session 的连续性。

4. 统一存储 Session,如使用 Redis

具体实现:

  • 使用一个中央化的数据存储系统(如 Redis)来保存所有的 Session 数据。
  • 每个服务实例通过网络调用来访问存储在 Redis 中的 Session 数据。
  • 可以使用 Spring Session 等框架来简化开发过程,减少对业务代码的影响。

优点:

  • 高度可扩展,可以轻松地处理大量并发用户。
  • 降低服务实例之间的耦合度,简化了服务实例的设计。
  • 支持集群部署,可以在多台 Redis 服务器之间实现高可用性和负载均衡。

缺点:

  • 需要额外的一次网络请求来访问中央化的 Session 存储系统,增加了请求的响应时间。
  • 对业务代码有一定的侵入性,需要进行相应的配置和集成工作。
  • 如果使用 Spring Session 等框架,可以减轻侵入性问题,但也引入了额外的框架依赖。
相关推荐
P.H. Infinity4 小时前
【RabbitMQ】03-交换机
分布式·rabbitmq
aloha_7894 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
dsywws5 小时前
Linux学习笔记之vim入门
linux·笔记·学习
龙哥·三年风水6 小时前
群控系统服务端开发模式-应用开发-个人资料
分布式·php·群控系统
A-超8 小时前
vue3展示pag格式动态图
笔记
u0101526588 小时前
STM32F103C8T6学习笔记2--LED流水灯与蜂鸣器
笔记·stm32·学习
funnyZpC8 小时前
quartz集群增强版🎉
java·分布式·开源·集群·定时任务
weixin_518285058 小时前
深度学习笔记10-多分类
人工智能·笔记·深度学习
丘狸尾8 小时前
ubuntu【桌面】 配置NAT模式固定IP
笔记
明达技术9 小时前
工业4.0时代下的分布式IO模块
分布式