【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【19】认证服务03—分布式下Session共享问题


持续学习&持续更新中…

守破离


【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【19】分布式下Session共享问题

  • session原理
  • 分布式下session共享问题
  • Session共享问题解决—session复制
  • Session共享问题解决—客户端存储
  • Session共享问题解决—hash一致性
  • Session共享问题解决—统一存储
  • Session共享问题解决—不同服务,子域session共享
  • 手动设置Cookie,手动拿取Cookie
  • 整合SpringSession
  • SpringSession核心原理
  • 参考

session原理

在这里插入图片描述

问题:不能跨不同域名共享

在这里插入图片描述

分布式下session共享问题

在这里插入图片描述

在这里插入图片描述

Session共享问题解决—session复制

在这里插入图片描述

优点 :web-server(Tomcat)原生支持,只需要修改配置 文件

缺点 :

  • session同步需要数据传输,占用大量网络带宽,降低了服务器群的业务处理能力
  • 任意一台web-server保存的数据都是所有web- server的session总和,受到内存限制无法水平扩展更多的web-server
  • 大型分布式集群情况下,由于所有web-server都全量保存数据,所以此方案不可取。

Session共享问题解决—客户端存储

在这里插入图片描述

优点

  • 服务器不需存储session,用户保存自己的 session 信息到 cookie 中。节省服务端资源

缺点

  • 都是缺点,这只是一种思路。
  • 具体如下:
  • 每次http请求,携带用户在cookie中的完整信息, 浪费网络带宽
  • session数据放在cookie中,cookie有长度限制 4 K,不能保存大量信息
  • session数据放在cookie中,存在泄漏、篡改、 窃取等安全隐患
  • 这种方式不会使用。

Session共享问题解决—hash一致性

在这里插入图片描述

优点:

  • 只需要改nginx配置,不需要修改应用代码
  • 负载均衡,只要hash属性的值分布是均匀的,多台 web-server的负载是均衡的
  • 可以支持web-server水平扩展(session同步法是不行的,受内存限制)

缺点:

  • session还是存在web-server中的,所以web-server重启可能导致部分session丢失,影响业务,如部分用户需要重新登录
  • 如果web-server水平扩展,rehash 后session 重新分布, 也会有一部分用户路由不到正确的session
  • 但是以上缺点问题也不是很大,因为session本来都是有有效期的。所以这两种反向代理的方式可以使用

Session共享问题解决—统一存储

在这里插入图片描述

优点:

  • 没有安全隐患
  • 可以水平扩展,数据库/缓存水平切分即可
  • web-server重启或者扩容都不会有 session 丢失

不足:

  • 增加了一次网络调用,并且需要修改应用代码;如将所有的getSession方法替换为从Redis查数据的方式。
  • redis获取数据比内存慢很多
  • 上面缺点可以用SpringSession完美解决

Session共享问题解决—不同服务,子域session共享

jsessionid这个cookie默认是当前系统域名的。当我们分拆服务,不同域名部署的时候,我们可以使用如下解决方案;

放大Cookie作用域

在这里插入图片描述

手动设置Cookie,手动拿取Cookie

gulimall-auth:OAuth2Controller

    @GetMapping("/oauth2.0/weibo/success")public String weibo(@RequestParam("code") String code, HttpSession session,HttpServletResponse httpServletResponse) throws Exception {Map<String, String> headers = new HashMap<>();Map<String, String> bodys = new HashMap<>();bodys.put("client_id", "3276999101");bodys.put("client_secret", "452bbefff4680ac8554b97799a8c12cb");bodys.put("grant_type", "authorization_code");bodys.put("redirect_uri", "http://auth.gulimall.com/oauth2.0/weibo/success");bodys.put("code", code);//1、根据code换取accessToken;HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token", headers, null, bodys);if (response.getStatusLine().getStatusCode() == 200) {//2、获取到了 socialUserAccessToken 进行处理String json = EntityUtils.toString(response.getEntity());SocialUserAccessToken socialUserAccessToken = JSON.parseObject(json, SocialUserAccessToken.class);
//            String uid = socialUserAccessToken.getUid();// 通过uid就知道当前是哪个社交用户//1)、当前用户如果是第一次进网站,进行自动注册(为当前社交用户生成一个会员信息账号,以后这个社交账号就对应指定的会员账号)R r = memberFeignService.socialLogin(socialUserAccessToken);if (r.getCode() == BizCodeEnume.SUCCESS.getCode()) {//登录或者注册这个社交用户//2)、登录成功就跳回首页/*** 手动设置Cookie*/MemberRespVo loginUser = r.getData(new TypeReference<MemberRespVo>() {});stringRedisTemplate.opsForValue().set("loginUser", JSON.toJSONString(loginUser));Cookie cookie = new Cookie("GULIMALL", "loginUser");cookie.setDomain("gulimall.com");cookie.setMaxAge(24 * 60 * 60);cookie.setPath("/");httpServletResponse.addCookie(cookie);session.setAttribute("loginUser", loginUser);return "redirect:http://gulimall.com";}}return "redirect:http://auth.gulimall.com/login.html";}

gulimall-product:IndexController

    @GetMapping({"/", "/index.html"})public String indexPage(Model model, HttpServletRequest httpServletRequest, HttpSession session) {/*** 手动获取Cookie*/Cookie[] cookies = httpServletRequest.getCookies();if (null != cookies && cookies.length > 0) {for (Cookie cookie : cookies) {if (cookie.getName().equalsIgnoreCase("GULIMALL")) {String loginUserKey = cookie.getValue();String json = stringRedisTemplate.opsForValue().get(loginUserKey);MemberRespVo loginUser = JSON.parseObject(json, new TypeReference<MemberRespVo>(){});session.setAttribute("loginUser", loginUser);}}}List<CategoryEntity> categorys = categoryService.listLevel1Categorys();model.addAttribute("categorys", categorys);return "index";}

@Controller
public class LoginController {@GetMapping("/login.html")public String loginPage() {if(stringRedisTemplate.opsForValue().get("loginUser") != null) return "redirect:http://gulimall.com";return "login";}
}

整合SpringSession

<!-- 1 整合SpringSession完成session共享问题 -->
<dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId>
</dependency>
# 2 整合SpringSession
spring.session.store-type=redis
#server.servlet.session.timeout=60m
# 3 配置Redis的连接信息(之前配过)
#spring.redis.host=xxx
#spring.redis.port=xxx
#spring.redis.password=xxx
@EnableRedisHttpSession // 4 整合Redis作为session存储
// 5 使用SpringSession【跟以前使用session的写法一样】
//第一次使用session;命令浏览器保存卡号。JSESSIONID这个cookie;
//以后浏览器访问哪个网站就会带上这个网站的cookie;
//子域之间; gulimall.com  auth.gulimall.com  order.gulimall.com
//应该做到:发卡的时候(指定域名为父域名),那么,即使是子域系统发的卡,也能让父域直接使用。
// 1、默认发的令牌。session=xxxxxxx。作用域:当前域;(SpringSession默认没有解决子域session共享问题)
// 2、使用JSON的序列化方式来序列化对象数据到redis中R r = memberFeignService.socialLogin(socialUserAccessToken);if (r.getCode() == BizCodeEnume.SUCCESS.getCode()) {//登录或者注册这个社交用户//2)、登录成功就跳回首页MemberRespVo loginUser = r.getData(new TypeReference<MemberRespVo>() {});session.setAttribute("loginUser", loginUser);
//6 配置序列化 + Cookie domain
// 解决子域session共享问题
@Configuration
public class GulimallSessionConfig {@Beanpublic CookieSerializer cookieSerializer(){DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();cookieSerializer.setDomainName("gulimall.com");cookieSerializer.setCookieName("GULISESSION");
//        cookieSerializer.setCookieMaxAge(); // 默认是浏览器的session级别,关闭浏览器就失效return cookieSerializer;}@Beanpublic RedisSerializer<Object> springSessionDefaultRedisSerializer() {return new GenericJackson2JsonRedisSerializer();}}
<!-- 7 给其他服务也整合好SpringSession后,直接取session中的数据即可  --><a  th:if="${session.loginUser!=null}">欢迎:[[${session.loginUser==null?'':session.loginUser.nickname}]]</a>
//    登录页面@GetMapping("/login.html")public String loginPage(HttpSession session) {
//        if(stringRedisTemplate.opsForValue().get("loginUser") != null) return "redirect:http://gulimall.com";Object attribute = session.getAttribute(AuthServerConstant.LOGIN_USER);if(attribute != null) return "redirect:http://gulimall.com";return "login";}

SpringSession核心原理

/*** SpringSession 核心原理 装饰者模式;* @EnableRedisHttpSession导入RedisHttpSessionConfiguration配置*      1、给容器中添加了一个组件*          SessionRepository = 》》》【RedisOperationsSessionRepository】==》redis操作session。session的增删改查封装类*      2、SessionRepositoryFilter == 》Filter: session'存储过滤器;每个请求过来都必须经过filter*          1、创建的时候,就自动从容器中获取到了SessionRepository;*          2、原始的request,response都被包装。SessionRepositoryRequestWrapper,SessionRepositoryResponseWrapper*          3、以后获取session。SessionRepositoryRequestWrapper.getSession();*          4、wrappedRequest.getSession();===> SessionRepository 中获取到的。*自动延期;用户只要没有关闭浏览器,SpringSession会自动续期,当然,用户关闭了浏览器,redis中的数据也是有过期时间的。*/

在这里插入图片描述

参考

雷丰阳: Java项目《谷粒商城》Java架构师 | 微服务 | 大型电商项目.


本文完,感谢您的关注支持!


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

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

相关文章

ASUS/华硕飞行堡垒8 FX506L FX706L系列 原厂win10系统 工厂文件 带F12 ASUS Recovery恢复

华硕工厂文件恢复系统 &#xff0c;安装结束后带隐藏分区&#xff0c;一键恢复&#xff0c;以及机器所有驱动软件。 系统版本&#xff1a;Windows10 原厂系统下载网址&#xff1a;http://www.bioxt.cn 需准备一个20G以上u盘进行恢复 请注意&#xff1a;仅支持以上型号专用…

域名、网页、HTTP概述

目录 域名 概念 域名空间结构 域名注册 网页 概念 网站 主页 域名 HTTP URL URN URI HTML 超链接 发布 HTML HTML的结构 静态网页 特点 动态网页 特点 Web HTTP HTTP方法 GET方法 POST方法 HTTP状态码 生产环境下常见的HTTP状态码 域名 概念 IP地…

基于.NET开源游戏框架MonoGame实现的开源项目合集

前言 今天分享一些基于.NET开源游戏框架MonoGame实现的开源项目合集。 MonoGame项目介绍 MonoGame是一个简单而强大的.NET框架&#xff0c;使用C#编程语言可以创建桌面PC、视频游戏机和移动设备游戏。它已成功用于创建《怒之铁拳4》、《食肉者》、《超凡蜘蛛侠》、《星露谷物…

【跟我学K8S】45天入门到熟练详细学习计划

目录 一、什么是K8S 核心功能 架构组件 使用场景 二、入门到熟练的学习计划 第一周&#xff1a;K8s基础和概念 第二周&#xff1a;核心对象和网络 第三周&#xff1a;进阶使用和管理 第四周&#xff1a;CI/CD集成和监控 第五周&#xff1a;实战模拟和案例分析 第六周…

XPointer 实例

XPointer 实例 1. 引言 XPointer 是一种用于定位 XML 文档中特定部分的语言。它是 XLink 的补充,允许用户在 XML 文档中创建链接,指向文档中的特定元素、属性或文本。XPointer 的强大之处在于其精确的定位能力,使得开发者能够创建更加丰富和动态的 XML 应用。 2. XPointe…

【Spring Boot】spring boot主启动类_内置服务

1、主启动类 1.1 定义与功能 Spring Boot的主启动类是一个特殊的Java类&#xff0c;用于启动Spring Boot应用程序。该类通常使用SpringBootApplication注解进行标注&#xff0c;这个注解是一个复合注解&#xff0c;包含SpringBootConfiguration、EnableAutoConfiguration和Co…

LRU Cache 双向链表以及STL list实现----面试常考

双向链表版本&#xff1a; #include <bits/stdc.h> using namespace std; struct Node{int key, value;Node* prev;Node* next;Node():key(0), value(0), prev(nullptr), next(nullptr){}Node(int k, int v):key(k), value(v), prev(nullptr), next(nullptr){} }; class…

【IT领域新生必看】Java中的对象创建魔法:小白也能掌握的五种方法

文章目录 引言为什么需要创建对象&#xff1f;创建对象的五种常见方式1. 使用 new 关键字示例&#xff1a; 2. 使用反射示例&#xff1a; 3. 使用克隆示例&#xff1a; 4. 使用序列化和反序列化示例&#xff1a; 5. 使用工厂方法示例&#xff1a; 选择合适的对象创建方式总结 引…

Spring容器Bean之XML配置方式

一、首先看applicationContext.xml里的配置项bean 我们采用xml配置文件的方式对bean进行声明和管理&#xff0c;每一个bean标签都代表着需要被创建的对象并通过property标签可以为该类注入其他依赖对象&#xff0c;通过这种方式Spring容器就可以成功知道我们需要创建那些bean实…

IPython代码块粘贴秘籍:效率与技巧的完美结合

标题&#xff1a;IPython代码块粘贴秘籍&#xff1a;效率与技巧的完美结合 在数据科学和Python编程的日常实践中&#xff0c;经常需要在IPython环境中快速有效地粘贴代码块。这个过程虽小&#xff0c;却对提升工作效率至关重要。本文将详细介绍如何在IPython中粘贴代码块&…

comsol随机材料参数赋值

comsol随机材料参数赋值 在comsol中定义外部matlab函数 在comsol中定义外部matlab函数 首选项&#xff0c;安全性&#xff0c;允许 材料中&#xff0c;将杨氏模量更改为变量函数 计算 应力有波动&#xff0c;可见赋值成功 也可以看到赋值的材料参数&#xff1a;

植物大战僵尸杂交版V2.1+修改器+融合版

植物大战僵尸杂交版v2.1 新增新植物&#xff0c;全新模式与玩法&#xff01; 内含窗口放大工具与修改器 主播同款游戏&#xff0c;下载使用即可&#xff01; 链接: https://pan.baidu.com/s/1znjbqgBSdqTJWZLBOhe5hA?pwdj6ra 提取码: j6ra

vulnhub--IMF

环境 攻击机&#xff1a;192.168.96.4 靶机&#xff1a;ip未知 主机探测 确定靶机ip为32的主机 端口扫描 访问80端口 外围打点 在contact.php页面源码中找到了flag1 之后没啥突破 但查看网络后发现contact.php页面请求的三个js文件的文件名很有特点&#xff0c;猜测是base64编码…

模型优化调参利器贝叶斯优化bayesian-optimization实践

早在之前很多项目尤其是预测类型的项目中&#xff0c;就已经比较广泛地在实用贝叶斯优化库了&#xff0c;这是一个非常出色的纯python实现的项目&#xff0c;地址在这里&#xff0c;如下所示&#xff1a; 写这篇文章主要有两个目的&#xff0c;一方面是觉得这个工具库挺不错的值…

零基础做项目---五子棋对战---day01

创建项目 这里使用阿里云服务器 https://start.aliyun.com/ 勾选 MyBatis Framework (在SQL分类下)MySQL Driver (在SQL分类下)WebSocket (在Messaging分类下)Spring Web (在Web分类下) 项目结构 消息发送机制 按照当前已有的知识&#xff0c;主要是HTTP HTTP自身是难以实现这…

c++ 里如何检测内存泄露:比如用了 new ,但没有用 delete

&#xff08;1 方法一&#xff09; 用 MFC 框架的 F5 不带断点的调试。可以在输出窗口提示是否有内存泄露。 &#xff08;2 方法二&#xff09; &#xff0c;在 main 函数中添加如下代码&#xff0c;用 F5 不带断点的调试&#xff1a; int main() {_CrtSetDbgFlag( _CRTDBG_A…

vue.js微商城后台管理系统

一.需要运行的效果 20240701-231456 二.代码&#xff08;解析&#xff09; 首先&#xff0c;为项目添加依赖&#xff1a; yarn add element-plus --save yarn vue-router4 --save 新建一个项目包&#xff0c;然后命名为商品管理&#xff0c;在components中新建几个vue文件。 …

React Hooks 深度解析

Hooks简介 诞生背景&#xff1a; 在React 16.8之前的版本中&#xff0c;组件主要分为函数组件和类组件两大类。函数组件简单轻量&#xff0c;但不支持状态&#xff08;state&#xff09;和生命周期方法&#xff1b;而类组件虽然功能强大&#xff0c;但编写和维护起来相对复杂。…

驱动开发系列-如何与硬件通信

目录 一:概述 二:I/O端口和I/O内存的概念 三:硬件寄存器(I/O寄存器)和内存 四:使用I/O端口 一:概述 驱动程序是软件与硬件之间的抽象层;因此,它需要与这两者对话,本文将向你展示驱动程序如何与硬件对话。并介绍I/O端口和I/O内存的概念。 二:I/O端口和I/O…

C++新特性

C新特性主要体现在语法改进和标准库扩充两个方面。以下是一些主要的C新特性&#xff1a; 语法改进 统一的初始化方法&#xff1a;C11扩大了用大括号括起的列表&#xff08;初始化列表&#xff09;的使用范围&#xff0c;使其可用于所有的内置类型和用户自定义的类型。这种定义…