在线教育平台项目总结

一、业务流程

1.企业(B)

内容管理、媒资、缓存、消息、任务调度、搜索

2.个人(C)

搜索、缓存、订单、支付、学习

二、关键技术

1.缓存三兄弟:

缓存穿透,高并发请求过来之后,查询数据库中存在数据,都发现缓存中没有,还是会去多次查数据库。如果查询数据库中不存在数据,高并发会一直查数据库,因为数据写入不到redis里。即请求穿透了缓存一直在查数据库。解决方案:1.参数校验,不符合规则直接返回2.把数据库中不存在数据也给缓存到redis,查缓存时也有该key,但是值为null。这种情况要加过期时间,防止数据库中什么时候真的有了该key。

缓存雪崩,缓存的大量key失效,因为他们设置了相同的缓存失效时间。解决方案:1.使用同步锁,只允许一个线程访问,性能不高。2.对同一类型的key设置不同的过期时间。3.缓存预热,取出来加随机的过期时间。

缓存击穿,大量并发访问同一个热点数据,热点数据失效后同时访问数据库。解决方案:1.同步锁,性能太低。不要直接在方法名上加synchronized,只锁查询数据库的代码,缓存查询可以高并发访问,锁进来后还要再查一次缓存。2.热点数据不过期。

2.JWT登录:

使用jwt(json web token令牌可以自己校验,无状态认证,不存储用户身份。有三部分,header(头部),内容(用户的信息),签名(前两部分想加再加密),资源认证服务有密钥.密钥分为对称性加密和非对称性加密。对称性能高(即认证服务的和资源服务的密钥一样,非对称加密认证自己保留私钥,公钥下发给客户端和资源服务。内容可以根据token还原,放一些公开信息(比如头像).管控起来后http接口测试就不能正常进行,要带token去访问。在SecurityContextHolder中可以拿到用户信息(存储在jwt的token中)

要自定义UserDetailService类连接用户数据库,传给username,连同用户名、密码、权限一起返回给spring security框架。密码不是明文存储,采用bcrypt加密,每次生成的密码都不一样。将用户信息转成json传回,否则没有头像等信息,这个过程中要将密码等敏感信息置空。获取的时候可以写一个工具类json转对象

由于有很多可能的提交信息方式,比如:账号密码,手机验证码,微信扫码,因此需要统一认证,新建一个DTO类。userdetailservice原本传入的是username,现在要传入的是DTO类的json串。使用fastjson

重写DAOAuthenticationProvider(DaoAuthenticationProvider通过UserDetailsService以及PasswordEncoder,将用户名密码替换成UserDetails和Authorities),authentication(认证)authorization(授权)不止使用密码校验,所以要重写方法。一个接口有很多个实现类,在service中增加名字(password_authservice,wx_authservice)

3.幂等性、索引同步:

本地消息表+任务调度的机制来完成分布式事务的最终数据一致性的控制。建的本地消息表和课程发布表在同一个数据库,使用数据库事务控制,保证发布了就一定会在消息表中,然后任务调度定时调度消息表存储给redis,es,minIO。若当中有失败的,则下次定时会继续发,已经成功的根据幂等性,会跳过。

4.分布式锁

本地锁每个JVM都会查一次数据库。实现方案:1.数据库乐观锁(谁update成功)2.基于redis的set nx(不存在才可以在redis里面存,看是否可以set成功),set lock01 01 NX EX 30要记得设置过期时间,否则其他拿不到锁,锁过期时间很难设置,可以手动删除锁,为了防止删除别人的锁,可以判断锁的值是不是自己设置的。代码不具有原子性,要借助lua脚本,让cpu一次性执行完毕,可能有断电等问题,过期时间的值还是不精确。3.zookeeper4.redisson,自旋锁(非阻塞锁),另起线程看门狗,看线程是否干完活,可以续过期时间。

悲观锁synchronized总认为有线程抢锁,拿到锁后再执行。乐观锁认为没有线程抢锁,尽管执行,如果没有执行成功就重试。

5.数据库事务控制:

关于文件上传过程中的事务控制,抽取出只有数据库操作的方法来加。在类内curProxy通过代理对象调用。文件名为md5值+.jpg ,.mp4.content-type来判断是图片还是文档、视频

脏读:指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚

不可重复读(Update):指的是在同一事务内,不同的时刻读到的同一批数据可能是不一样的

幻读(Insert):假设事务A对某些行的内容作了更改,但是还未提交,此时事务B插入了与事务A更改前的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现好像刚刚的更改对于某些数据未起作用。

6.熔断降级:

Hystrix框架实现熔断、降级处理。开启feign熔断保护,定义降级逻fallbackFactory,降级处理逻辑(返回一个null对象,上游服务请求接口得到一个null说明执行了降级处理。)@feignClient,微服务雪崩A->B->C,Cdown了,会影响B进而影响A。下游服务异常熔断后,上游服务不再调用异常的微服务而是执行了降级处理逻辑(一种保护系统的手段),使用hystrix框架实现熔断、降级处理。解决:定义fallback类,重新处理,这种方法拿不到熔断异常信息。定义fallbackfactory类,出现熔断之后,上游调用create方法来进行降级处理(可以拿到熔断的异常信息)

7.异常处理:

抛给框架处理。运用AOP思想,@ControllerAdvice控制增强,通常和@ExceptionHandler结合使用。增强类处理。在base里写,和前端约定返回的异常信息模型,新建本项目自定义异常类型(继承runtimeexception),新建类写异常处理(可以区别捕获的异常类型)。

异常处理除了输出在日志中,还需要提示给用户。1.自定义项目异常类,使用该类的cast函数在业务代码中throw异常,在全局异常处理器(加了@RestControllerAdvice控制器增强和@ExceptionHandler)中处理该异常,定义restErrorResponse类实现序列化接口return给前端。

异常处理器中要解析jsr303的异常,否则会报unknow的统一异常信息,因为他不属于xuecheng的程序员自定义类型异常。前端后端都要校验,为了防止使用postman等访问后端。

多个接口共用模型类(新增id为空,但修改id不为空),使用分组校验。

8.权限控制:

分两种方式,基于角色的访问控制和基于资源的访问控制。if里面写的是角色还是是否有这个权限(一个属性字段)。基于资源的访问控制健壮性更好。使用@PreAuthorize("hasAuthority('权限标识符')")进行控制,标识符会在数据库中定义。在方法前面加该注解,拥有此权限才可以访问该方法。

细粒度授权(数据权限),对某一资源有访问权限,但是可以访问到的数据不一样,比如两个培训机构。course_base中有培训机构id。在service接口根据参数去做,security框架无法实现

9.跨域:

跨域是基于浏览器的同源策略,协议(https)、主机、端口三者,

1.通过script标签的src属性进行跨域请求

2.在响应头添加 Access-Control-Allow-Origin:*

3.通过nginx代理跨域,因为服务端之间没有跨域

10.页面静态化方案

课程信息页面的访问量较大,并且课程信息发布后在一段时间不会修改,这里使用Freemarker(thymeleaf)静态化技术将课程信息页面静态化,提前生成html页面并通过媒资管理模块的文件服务上传到文件系统,用户浏览课程信息页面通过分布文件系统浏览,提高了课程信息页面访问性能。

11.JVM的GC机制:

(1)哪些内存需要回收?

堆和方法区,程序计数器、虚拟机栈、本地方法栈3个区域是随线程而生,随线程而灭的

(2)什么时候回收?

判断对象是否可以回收,有两种比较经典的判断策略。

  • 引用计数算法,count+1-1,=0时失效
  • 可达性分析算法,为起点开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots 没有任何引用链相连时。

(3)如何回收?

  • 标记-清除(Mark-Sweep)算法,大量不连续的内存碎片
  • 复制(Copying)算法,(新生代)当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
  • 标记-整理(Mark-Compact)算法,(老生代)让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

12.输入网址到显示:

1、输入网址
2、DNS解析获取域名对应的IP地址
3、建立TCP连接
4、web浏览器向web服务器发送HTTP请求
5、服务器的永久重定向响应
6、浏览器跟踪重定向地址
7、web服务器做出应答
8、浏览器显示 HTML
9、浏览器发送请求获取其他嵌入在 HTML 中的资源
10、web服务器关闭TCP连接

三、组件

1.Nacos:

服务注册中心和配置中心

namespace、group、dataid。

namespace(开发环境,测试环境,上线环境)和group(学成在线,瑞吉外卖)。

Dataid:  包括三部分:服务名、环境名、扩展名,

content-service-dev.yaml配置文件  由(content-service)-(dev). (yaml)三部分组成

server:servlet:context-path: /contentport: 63040test_config:a: 3ab: 3b#配置本地优先
spring:cloud:config:override-none: true

2.Gateway:

负载均衡、路由转发、统一鉴权

前端请求到Nginx,通过负载均衡到Gateway网关,通过网关将请求转发至各个微服务。网关从nacos读取服务地址

3.Redis

白名单、热点数据

实现分布式锁,避免课程查询等公开接口出现缓存击穿问题

4.RabbitMQ

将支付结果发通过给fanout类型的交换机,由交换机将消息广播发送至每个接收支付结果的微服务。

5.Elasticsearch

倒排索引,对课程发布信息进行索引和搜索。

布尔查询、聚合搜索、过滤器、高亮显示等功能

6.XXL-Job

由调用中心和执行器组成,调用中心负责按任务调度策略向执行器下发任务,执行器负责接收任务执行任务。主要用于索引同步

配置调度过期策略和阻塞处理策略,避免同一个执行器多次重复执行同一个任务

调度过期策略:忽略:调度过期后,忽略过期的任务,从当前时间开始重新计算下次触发时间;
阻塞处理策略:丢弃后续调度。

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

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

相关文章

升降梯人数识别摄像机

升降梯人数识别摄像机是一种智能监测设备,主要用于实时识别和计算升降梯内乘客的数量。通过搭载先进的图像识别技术和人工智能算法,该设备可以准确监测乘客进出数量,提供重要数据支持和信息反馈,帮助管理人员有效管理升降梯运行&a…

STM32学习和实践笔记(4): 分析和理解GPIO_InitTypeDef GPIO_InitStructure (a)

深入分析及学习一下上面这一段代码的构成与含义。 首先,这个GPIO_InitTypeDef GPIO_InitStructure;其实与int a 是完全类似的语法格式以及含义。 GPIO_InitStructure就相当于a这样一个变量。不过从这个变量的名字可以知道,这是一个用于GPIO初始化的结构…

界面控件DevExtreme JS ASP.NET Core 2024年度产品规划预览(一)

在本文中我们将介绍今年即将发布的v24.1附带的主要特性,这些特性既适用于DevExtreme JavaScript (Angular、React、Vue、jQuery),也适用于基于DevExtreme的ASP.NET MVC/Core控件。 注意:本文中列出的功能和特性说明官方当前/预计的发展计划&a…

hcip实验4:gre mgre ppp综合实验

实验拓扑: 实验目的: 1.R5为ISP,只能进行IP地址配置,其所有地址均配为公有IP地址 2.R1和R5间使用PPP的PAP认证,R5为主认证方;R2与R5之间使用ppp的CHAP认证,R5为主认证方;R3与R5之间使用HDLC封装; 3.R1、R…

MQ消息队列详解以及MQ重复消费问题

MQ消息队列详解以及MQ重复消费问题 1、解耦2、异步调用3、流量削峰4、MQ重复消费问题,以及怎么解决?4.1、重复消费产生4.2、解决方法: https://blog.csdn.net/qq_44240587/article/details/104630567 核心的就是:解耦、异步、削锋…

当面试官问你插入排序算法,你敢说自己会吗?

算法学习的重要性 在程序员的世界里,算法就如同一座桥梁,连接着问题与解决方案,是实现优秀程序的关键。 掌握算法,就能够在面对各种问题时,找到最合适的解决方法,以最少的时间和空间,实现最优的…

波长可调激光器中的增益芯片和SOA

----翻译自SATO Kenji,ZHANG Xiaobo于2019年发表的文章 摘要: 本文讨论了用于波长可调激光器(TL)的半导体光放大器(SOA)和增益芯片的设计规则。即与常规SOA或激光器相似,也有一些不同之处。位…

酷开科技不断深耕智能电视领域,用酷开系统带给消费者更多可能性

在这个网络快速发展的时代,电视行业也发生了巨大变革。与以往单纯的“看”电视不同,人们不再满足于现有的状态,消费者对电视娱乐的追求更加丰富,这也就带给智能电视产业无限的发展可能。酷开科技瞄准这一产业趋势,不断…

家庭影院触摸屏中应用的电容式触摸芯片

家庭影院的主要组成部分包括显示设备、音响设备、信号源和接线设备等。其中,显示设备通常采用高清电视或投影仪,音响设备包括功放、音箱、低音炮等,信号源可以是蓝光光盘、游戏机、有线电视、网络电视等多种媒体设备。 家庭影院的影像信号通…

[C#]winform使用OpenCvSharp实现透视变换功能支持自定义选位置和删除位置

【透视变换基本原理】 OpenCvSharp 是一个.NET环境下对OpenCV原生库的封装,它提供了大量的计算机视觉和图像处理的功能。要使用OpenCvSharp实现透视变换(Perspective Transformation),你首先需要理解透视变换的原理和它在图像处理…

vulhub打靶记录——healthcare

文章目录 主机发现端口扫描FTP—21search ProPFTd EXPFTP 匿名用户登录 web服务—80目录扫描search openemr exp登录openEMR 后台 提权总结 主机发现 使用nmap扫描局域网内存活的主机,命令如下: netdiscover -i eth0 -r 192.168.151.0/24192.168.151.1…

Android的图片加载框架

Android的图片加载框架 为什么要使用图片加载框架?图片加载框架1. Universal Image Loader [https://github.com/nostra13/Android-Universal-Image-Loader](https://github.com/nostra13/Android-Universal-Image-Loader)2. Glide [https://muyangmin.github.io/gl…

MySQL的多层SP中Cursor的m_max_cursor_index相关BUG分析

源码分析丨MySQL的多层SP中Cursor相关BUG 一、问题发现 在一次开发中在sp中使用多层cursor的时候想知道每层的m_max_cursor_index值分别是多少,以用来做后续开发。于是做了以下的试验,但是发现第一个level2那层的m_max_cursor_index的值有点问题。 注&…

基于SpringBoot和Vue的房产销售系统的设计与实现

今天要和大家聊的是一款基于SpringBoot和Vue的房产销售系统的设计与实现 !!! 有需要的小伙伴可以通过文章末尾名片咨询我哦!!! 💕💕作者:李同学 💕&#x1f…

【Spring实战项目】SpringBoot3整合WebSocket+拦截器实现登录验证!从原理到实战

🎉🎉欢迎光临,终于等到你啦🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟持续更新的专栏《Spring 狂野之旅:从入门到入魔》 &a…

MySQL-linux安装-万能RPM法

一、MySQL的Linux版安装 1、 CentOS7下检查MySQL依赖 1. 检查/tmp临时目录权限(必不可少) 由于mysql安装过程中,会通过mysql用户在/tmp目录下新建tmp_db文件,所以请给/tmp较大的权限。执行 : chmod -R 777 /tmp2. …

Aurora8b10b(2)上板验证

文章目录 前言一、AXI_Stream数据产生模块二、上板效果总结 前言 上一篇内容我们已经详细介绍了基于aurora8b10b IP核的设计,本文将基于此进一步完善并且进行上板验证。 设计思路及代码思路参考FPGA奇哥系列网课 一、AXI_Stream数据产生模块 AXIS协议是非常简单的…

Boost之Log: (3)、简单封装

设计目标: 1、每个Logging source对应一个目录,可以设置日志文件数,日志大小,目录名,文件名等 2、所有logging source日志目录都在一个根目录下。 3、可以动态创建和删除logging source 4、打印出日期时间和日志严重等级 示例代码…

前端试题2#记录

1、介绍以下CSS的盒子模型 盒子模型分为两种: (1)第一种是W3c标准的盒子模型(标准盒模型) width和height:内容的宽度、高度(不是盒子的宽度、高度)。padding:内边距。…