【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【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;仅支持以上型号专用…

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

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

【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实…

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文件。 …

C++新特性

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

【C语言】指针(1)--入门理解

目录 一、内存和地址 二、指针变量和地址 三、指针变量类型的意义 一、内存和地址 只要讲指针就离不开内存 因为指针就是访问内存的 计算上CPU&#xff08;中央处理器&#xff09;在处理数据的时候&#xff0c;需要的数据是在内存中读取的&#xff0c;处理后的数 据也会放…

PY32F030高性能单片机,主频高达48M,最大64 KB 闪存,8 KB SRAM

PY32F030是普冉的一颗32位高性能MCU&#xff0c;采用32 位 ARM Cortex-M0 内核&#xff0c;高达16~64 Kbytes Flash 和 2~8 Kbytes SRAM 存储器&#xff0c;最高 48 MHz 工作频率。PY32F030 单片机的工作温度范围为 -40 ~ 105 C&#xff0c;工作电压范围为1.7 ~ 5.5 V&#xff…

多语言版在线出租车预订完整源码+用户应用程序+管理员 Laravel 面板+ 司机应用程序最新版源码

源码带PHP后台客户端源码 Flutter 是 Google 开发的一款开源移动应用开发 SDK。它用于开发 Android 和 iOS 应用&#xff0c;也是为 Google Fuchsia 创建应用的主要方法。Flutter 小部件整合了所有关键的平台差异&#xff0c;例如滚动、导航、图标和字体&#xff0c;可在 iOS 和…

DevOps实战:使用GitLab+Jenkins+Kubernetes(k8s)建立CI_CD解决方案

一.系统环境 本文主要基于Kubernetes1.21.9和Linux操作系统CentOS7.4。 服务器版本docker软件版本Kubernetes(k8s)集群版本CPU架构CentOS Linux release 7.4.1708 (Core)Docker version 20.10.12v1.21.9x86_64CI/CD解决方案架构图:CI/CD解决方案架构图描述:程序员写好代码之…

ASP.NET MVC-razor编写-2-svg中使用js+添加事件监听

环境&#xff1a;win10 效果 初始状态&#xff1a; 鼠标移入某个text&#xff08;比如KS primer&#xff09;时&#xff0c;text和连接的线条与箭头都变色&#xff1a; 鼠标移出时回复正常。 如果是移入另一种红色的text&#xff08;比如Cell Sceening Tag&#xff09;&…

创建本地仓库

一、新建挂载目录 二、将挂载本地镜像挂载到目录 三、配置yum仓库 一、新建挂载目录 mkdir /BenDiCangKu 二、将挂载本地镜像挂载到目录 1、先连接本地光盘 2、挂载光盘 mount /dev/sr0 /BenDiCangKu 3、查看挂载 由此可见挂载成功 三、配置yum仓库 1、新建yum仓库文件…

php简单商城小程序系统源码

&#x1f6cd;️【简单商城小程序】&#x1f6cd;️ &#x1f680;一键开启&#xff0c;商城搭建新体验&#x1f680; 你还在为繁琐的商城搭建流程头疼吗&#xff1f;现在&#xff0c;有了简单商城系统小程序&#xff0c;一切变得轻松又快捷&#xff01;无需复杂的编程知识&a…

构建Android studio版的CarSystemUI工程时因为包名一致导致BuildConfig问题

项目场景&#xff1a; 公司计划开发杰发AC8025-Android 12版本车载平台&#xff0c;前期预研需要构建Android studio版的CarSystemUI工程 问题描述 AAOS车载项目里面的CarSystemUI源码默认无Android studio版本&#xff0c;为了后期快速开发调试需要构建Android studio能直接…