学成在线系统
学成在线项目是一个专门针对成人职业技能教育的网络课堂系统,网站提供了职业技能培训的相关课程,培训机构可以在平台入驻、发布课程,运营人员对发布的课程进行审核,审核通过后课程才可以发布成功,课程包括免费和收费两种形式,对于免费课程可以直接选课学习,对于收费课程在选课后需要支付成功才可以继续学习。
项目主要包括:内容管理、媒资管理、订单支付、认证授权、课程搜索、选课学习等模块。
1、内容管理
业务流程
1、登录教学机构,进入课程管理
2、维护课程信息,添加一门课程需要填写课程的基本信息、上传课程图片、课程营销信息、课程计划、上传课程视频、课程师资信息等内容。
3、课程信息编辑完成,通过课程预览确认无误后提交课程审核。
4、待运营人员对课程审核通过后方可进行课程发布。
运营人员的业务流程如下:
1、查询待审核的课程信息。
2、审核课程信息。
3、提交审核结果。
课程审核状态:未提交、已提交、审核通过、审核未通过
课程发布状态:未发布、已发布、已下线
此功能牵涉到的表有, 课程基础信息表、课程的营销表、课程计划表、课程师资信息表、课程分类表、课程计划媒资表、课程审核记录表、课程预发布表、课程发布表、课程消息表、课程消息历史表 当然还有数据字典表
课程审核
1、新增一门课程后它的审核状为”未提交“,发布状态为”未发布“。
2、课程信息编辑完成,教学机构人员执行”提交审核“操作。此时课程的审核状态为”已提交“。
3、当课程状态为已提交时运营平台人员对课程进行审核。
4、运营平台人员审核课程,结果有两个:审核通过、审核不通过。
5、课程审核过后不管状态是通过还是不通过,教学机构可以再次修改课程并提交审核,此时课程状态为”已提交“。此时运营平台人员再次审核课程。
6、课程审核通过,教学机构人员可以发布课程,发布成功后课程的发布状态为”已发布“。
7、课程发布后通过”下架“操作可以更改课程发布状态为”下架“
培训机构的教师 提交审核 会将4张表的信息添加到预发布表中,运营人员进行 课程审核 审核的是预发布表中的数据,而培训机构的教师修改的是那4张表的数据。当审核通过发布课程的时候,将预发布表的数据拷贝到发布表,并删除预发布表。
使用本地消息表加任务调度的方式来解决了分布式事务。
页面静态化
当数据变化不频繁,一旦生成静态页面很长一段时间内很少变化,此时可以考虑使用页面静态化。
课程发布
课程发布后如何快速的找到这们课 如何如何快速的查看课程信息
存Elasticsearch索引中,方便我们搜索,
除了将课程信息添加到发布表中,把它添加到Elasticsearch索引库中,
把它生成静态页面上传到分布式文件系统minio中。
点击发布 将课程预发布表的数据写到课程发布表 课程消息表添加一条数据,并且删除课程预发布表的数据,此时任务调度开始扫描消息表,查询课程的详细信息,存到缓存中,存到Elasticsearch索引库中,把它生成静态页面上传到minio中,最后把消息表数据添加到消息历史表并把消息表删除。
使用本地消息表加任务调度的方式解决分布式事务,保存数据的最终一致性。
如何保证任务的幂等性,
消息表里存一些状态字段标识,处理状态 初始、成功、失败,乐观锁
分片广播 可以最大限度的发挥执行器的性能
如何保证任务不重复执行 任务调度
路由策略 采用分片广播
调度过期策略 采用忽略,
阻塞调度策略 采用丢弃任务
这样就可以避免同一个执行器多次执行同一个任务
2、媒资管理
对文件进行统一管理
媒资管理的主要管理对象是图片、文档、视频等,包括:媒资文件的查询、文件上传、视频处理等。
媒资查询:教学机构查询自己所拥有的媒资信息。
文件上传:包括上传图片、上传文档、上传视频。
视频处理:视频上传成功,系统自动对视频进行编码处理。
文件删除:教学机构删除自己上传的媒资文件。
此功能牵涉到的表 媒资文件表、待处理视频表、视频处理历史表、课程计划与媒资表、课程计划表
2.1.1上传图片
教学机构人员在课程信息编辑页面上传课程图片,课程图片统一记录在媒资管理系统minio。
2.1.2 上传视频
媒资管理页面
进入媒资管理页面可以查询本机构上传的媒资文件,点击 上传视频 就可以选择自己要上传 的视频。自动执行文件上传,视频上传成功会自动转码处理(任务调度)。
2.1.3媒资审核
由运营人员登入系统进入媒资管理页面,查找待审核媒资,进行审核,审核通过后才可以在
媒资管理页查询到。若审核不通过需要填写审核意见。
2.1.4绑定媒资
在课程计划里面添加上传的视频或文件
2.2文件上传过程
文件上传前先检查 视频是否存在 获取文件的MD5码 是否相等,后面视频上传后也用MD5码来校验文件的完整性。
3、认证授权
认证:判断用户有没有登录,简单的来说查一下数据库看有没有该用户
授权:判断用户没有权限,有权限然它访问,没权限不让它访问
授权加上 所有的controller当中需要授权 加上@PreAuthorize(“hasAuthority(‘p1’)”)
指定权限字段 ,只有拥有此权限字段的用户才能访问。
SpringSecurity框架基于OAuth2协议实现的单点登录
OAuth2提供授权码模式
输入账号和密码或者微信扫码 都会统一进入认证服务,就会判断用户身份 合法不合法了,
如果 合法 认证成功之后会颁发令牌,存在浏览器的cookie用户携带令牌访问微服务了。
如果不合法,就从新登录。
微信扫码 整合SpringSecurity框架基于OAuth2协议实现的
点击扫码登录,会弹出一个二维码,用微信扫一下,此时会用户的信息已经存到微信官方,点击确认登录 就能授权码 ,通过授权码获取用户信息,查一下数据库如果没有,将数据存到数据库,如果有就登录成功。
appid 密钥、跳转路径
1、需要定义接口接收微信下发的授权码。
2、收到授权码调用微信接口申请令牌。
3、申请到令牌调用微信获取用户信息。
4、获取用户信息成功将其写入本项目用户中心数据库。
5、最后重定向到浏览器自动登录。
Oauth2是一个标准的开放的授权协议,应用程序可以根据自己的要求去使用Oauth2,本项目使用Oauth2实现如下目标:
1、学成在线访问第三方系统的资源。
本项目要接入微信扫码登录所以本项目要使用OAuth2协议访问微信中的用户信息。
2、外部系统访问学成在线的资源 。
同样当第三方系统想要访问学成在线网站的资源也可以基于OAuth2协议。
3、学成在线前端(客户端) 访问学成在线微服务的资源。
本项目是前后端分离架构,前端访问微服务资源也可以基于OAuth2协议进行认证。
JWT令牌 是个无状态认证方式 服务器不存用户的认证信息,是在客户端存。
用户认证成功之后,会向客户端发一个令牌,用户携带令牌来访问资源。
如何校验令牌的合法性
JWT有三部分组成 第一部分令牌的头信息(令牌的编码,使用的算法),第二部分令牌的内容(用户的信息),第三部分令牌的签名,这个部分使用base64url将前两部分进行编码,此部分用于防止jwt内容被篡改
使用的Base64Url 编码还可以还原
网关的作用:
路由转发,认证校验jwt令牌的合法性 还维护了一份白名单
微信扫码登录
1、 统一认证入口(账号密码认证、微信扫码认证)
2、 统一认证参数
3、 不管什么认证方式,都需要统一实现AuthSerivc接口
4、 这个地方使用了策略模式 账号密码方式登录实现类需要实现AuthSerivce接口,扫码登录的实现类也需要AuthSerivc接口
4、选课学习
学生选课、下单支付、学生学习的整体流程
网站的课程有免费和收费两种,对于免费课程学生选课后可直接学习,对于收费课程学生需要下单且支付成功之后选课、学习。
对于收费课程 点击支付宝支付,会添加选课记录、创建订单、生成二维码然后用户开始扫码,扫码的时候就会请求第三方平台 ,输入支付密码完成支付,支付完成之后第三方会支付通知。当然我们的系统也会请求第三方主动查询支付结果。最后学习中心会查询支付结果。如果已付费的课程就会把该课程加入我的课程表,学生可以直接直接学习了。
牵涉到的表 课程选课记录表、我的课程表、学习记录表 我的课程表记录的选课表的id
添加选课
选课中心服务调用内容管理 通过课程id、机构id查询查询已发布的课程
对于免费的课程,课程信息写到选课记录表并且状态是成功、写到我的课程表
对于收费的课程 需要创建订单,用户支付成功之后,会添加到选课记录表的状态是已支付
添加到我的课程表
5、订单支付
牵涉到的表 订单表、订单商品表、订单记录表、订单表的数据来源于选课记录表
第一步 向支付宝系统下订单
第二步 用户完成支付
第三步 支付结果通知
说明 用户扫码,二维码其实就是请求地址 会调用我们本地的接口,然后会调用支付宝的sdk,会向支付宝系统发送请求在他的系统会创建订单,支付宝就会相应一个json,如果是手机扫码的话唤起支付宝客户端然后用户输入密码进行支付,完成支付,(主动查询,被动通知)后面就是支付通知,要么主动查询获取支付结果,要么等支付宝通知支付结果。
最后可能会有一个退款接口,还有一个对账接口。
订单号、交易号、交易结果
下单接口、结果查询接口、结果通知接口、退款接口、对账
1、请求学习中心服务创建选课记录
2、请求订单服务创建商品订单、生成支付二维码。
3、用户扫码请求订单支付服务,订单支付服务请求第三方支付平台生成支付订单。
4、前端唤起支付客户端,用户输入密码完成支付。
5、第三方支付平台支付完成发起支付通知。
6、订单支付服务接收第三方支付通知结果。
7、用户在前端查询支付结果,请求订单支付服务查询支付结果。
8、订单支付服务向学习中心服务通知支付结果。
9、学习中心服务收到支付结果,如果支付成功则更新选课记录,并添加到我的课程表。
6、我的学习
用户通过课程详情界面点击马上学习 进入 视频插放界面进行视频点播。
获取视频资源时进行学习资格校验,如下图:
拥有学习资格则继续播放视频,不具有学习资格则引导去购买、续期等操作。
如何判断是否拥有学习资格?
首先判断是否为试学视频,如果为试学视频则可以正常学习。
如果为非试学课程首先判断用户是否登录,如果已登录则判断是否选课,如果已经选课且没有过期可以正常学习。
详细流程如下图:
个人中心页面
缓存穿透
就是查询数据库不存在的数据,导致缓存没有作用,大量并发请求到数据库,对我们的数据库造成很大的压力。
解决方案:
①如果id有一定的规则可以增加校验,比如长整型都是1开头,不是长整型或1开头就直接返回
②当我们在数据库查不到数据的时候,向缓存存入一个空值或特殊值,并且设置过期时间如30秒
③使用布隆过滤器,可以将我们的课程id全部放到过滤器,通过过滤器查得到0说明在数据库不存在,直接返回就不查数据库了
缓存雪崩
在一个时间段内,缓存中的大量数据同时失效或者缓存服务不可用,导致大量的请求直接访问数据库,从而导致造成系统性能下降或宕机。
解决方案:
①synchronized同步锁,但性能不太高
②设置随机的过期时间,保证key的过期时间不同
③缓存预热,定时任务,源源不端的将数据放到缓存中。
缓存击穿
大量并发访问同一个热点数据,当热点数据失效后同时去请求数据库,瞬间耗尽数据库资源,导致数据库无法使用。
解决方案:
①synchronized同步锁,但性能不太高,尽量缩小锁的范围
②不设置过期时间
分布式锁
就是把锁单独部署起来,由多个jvm进程争抢同一个锁。
实现方案
①基于数据库实现乐观锁
②redis提供了分布式锁的实现方案,比如:set nx、redisson
分布式任务调度 xxl-job
执行器 :专门执行任务的,是分布式部署的
调度中心:用来统一的协调和管理执行器
1、执行器通过配置和注解注册到调度中心
2、调度中心根据任务策略向执行器下发任务
3、执行器执行完任务,异步告诉调度中心是否成功,并且记录日志
目标: 执行器弹性扩容、任务不能重复执行等
执行器将自己的信息 注册到 调度中心,然后调度中心根据任务策略向执行器下发任务
方法上添加注解@xxl-job(“任务名称”)
路由策略采用 分片广播 可以最大限度提高分布式的执行能力(分片参数 执行器的序号、执行器的总数)
调度过期策略 采用忽略,