文章目录
- 一,225-商城业务-认证服务-分布式session不共享不同步问题
- 1,首页无用户信息
- 2,定位
- 3,谷粒商城session、cookie必须解决的两大问题
- 3.1. auth.gulimall.com 和 gulimall.com 的 cookie 信息不能共享
- 3.2. 分布式服务间的 session 不能共享
- 二,226-商城业务-认证服务-分布式session解决方案原理
- 1. 服务间 Session 复制
- 2. 客户端存储 Cookie,服务端无状态
- 3. 一致性 Hash
- 4. 统一存储 Session,如使用 Redis
一,225-商城业务-认证服务-分布式session不共享不同步问题
1,首页无用户信息
谷粒商城首页,点击超链接您好,请登录
,正常情况下应该跳转到Auth模块的login页面,登录成功后,会重定向到首页,超链接您好,请登录
应该替换为用户名。
但是实际开发过程中出现了这样一个问题,登录成功后,超链接您好,请登录
未被替换,再次点击这个超链接,不会跳转到登录界面,说明后台认为已经登录成功,直接重定向到首页了,但是首页没有拿到用户信息。
F12查看Application信息,也没有发现session
和cookie
信息。
2,定位
梳理登录流程,看看问题可能出现在哪个环节。
- 首页点击超链接
您好,请登录
- 跳转到
auth.gulimall.com/login.html
,这里很关键,商城用户认证模块的域名和首页域名不一致 - 认证模块完成用户验证后,将用户信息保存在
session
中 auth
模块的前端页面login.html
将session
信息保存在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不能共享;
3.1. auth.gulimall.com 和 gulimall.com 的 cookie 信息不能共享
原因与原理:
-
域名限制: Cookie 是基于 HTTP 协议中的 Set-Cookie 头来设置的。根据 HTTP 协议的规定,每个 Cookie 都有一个
Domain
属性,这个属性定义了该 Cookie 可以被哪些域名下的请求访问。如果一个 Cookie 设置为.example.com
,那么所有以example.com
结尾的子域都可以访问这个 Cookie。 -
子域名隔离: 在您的例子中,
auth.gulimall.com
和gulimall.com
分别代表了不同的子域。默认情况下,浏览器不会在这些不同的子域间共享 Cookie。例如,如果 Cookie 的Domain
属性设置为auth.gulimall.com
,则它只能被auth.gulimall.com
访问,而不能被gulimall.com
或其他子域访问。 -
SameSite 属性: 此外,现代浏览器还支持
SameSite
属性来进一步控制 Cookie 的行为。如果设置了SameSite=Strict
或SameSite=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 等框架,可以减轻侵入性问题,但也引入了额外的框架依赖。