1. 需求分析
1.1 介绍
媒资管理系统是每个在线教育平台所必须具备的,查阅百度百科对它的定义如下:
媒体资源管理(Media Asset Management,MAM)系统是建立在多媒体、网络、数据库和数字存储等先进技术基础上的一个对各种媒体及内容(如视/音频资料、文本文件、图表等)进行数字化存储、管理以及应用的总体解决方案,包括数字媒体的采集、编目、管理、传输和编码转换等所有环节。其主要是满足媒体资源拥有者收集、保存、查找、编辑、发布各种信息的要求,为媒体资源的使用者提供访问内容的便捷方法,实现对媒体资源的高效管理,大幅度提高媒体资源的价值。
每个教学机构都可以在媒资系统管理自己的教学资源,包括:视频、教案等文件。
目前媒资管理的主要管理对象是视频、图片、文档等,包括:媒资文件的查询、文件上传、视频处理等。
媒资查询:教学机构查询自己所拥有的媒资信息。
文件上传:包括上传图片、上传文档、上传视频。
视频处理:视频上传成功,系统自动对视频进行编码处理。
文件删除:教学机构删除自己上传的媒资文件。
下图是课程编辑与发布的整体流程,通过下图可以看到媒资管理在整体流程的位置:
1.2 业务流程
1.2.1 上传图片
教学机构人员在课程信息编辑页面上传课程图片,课程图片统一记录在媒资管理系统。
下图是上传图片的界面:
1.2.2 上传视频
1、教学机构人员进入媒资管理列表查询自己上传的媒资文件。
点击“媒资管理”
进入媒资管理列表页面查询本机构上传的媒资文件。
2、教育机构用户在"媒资管理"页面中点击 "上传视频" 按钮
点击“上传视频”打开上传页面
3、选择要上传的文件,自动执行文件上传,视频上传成功会自动处理
1.2.3 处理视频
对需要转码处理的视频系统会自动对其处理,处理后生成视频的URL。
处理视频没有用户界面,完全是后台自动执行。
1.2.4 审核媒资
审核媒资包括程序自动审核和人工审核,程序可以通过鉴黄接口(https://www.aliyun.com/product/lvwang?spm=5176.19720258.J_3207526240.51.e93976f4rSq796)审核视频,对有异议的视频由人工进行审核。
1.运营用户登入运营平台并进入媒资管理页面,查找待审核媒资
2.点击列表中媒资名称链接,可预览该媒资,若是视频,则播放视频。
3.点击列表中某媒资后的"审核" 按钮,既完成媒资的审批过程
点击“审核”,选择审核结果,输入审核意见
1.2.5 绑定媒资
课程计划创建好后需要绑定媒资文件,比如:如果课程计划绑定了视频文件,进入课程在线学习界面后点课程计划名称则在线播放视频。如下图
如何将课程计划绑定媒资呢?
1.教育机构用户进入课程管理页面并编辑某一个课程,在"课程大纲"标签页的某一小节后可点击”添加视频“。
2.弹出添加视频对话框,可通过视频关键字搜索已审核通过的视频媒资
3.选择视频媒资,点击提交按钮,完成课程计划绑定媒资流程。
课程计划关联视频后如下图:
1.3 数据模型
本模块媒资文件相关的数据表如下:
媒资文件表:存储文件信息,包括图片、视频、文档等。
media_process: 待处理视频表。
media_process_history: 视频处理历史表,记录已经处理成功的视频信息。
媒资文件与课程计划绑定关系表如下:
2. 搭建模块
2.1 架构的问题分析
当前要开发的是媒资管理服务,目前为止共三个微服务:内容管理、系统管理、媒资管理,如下图:
后期还会添加更多的微服务,当前这种由前端直接请求微服务的方式存在弊端:
如果在前端对每个请求地址都配置绝对路径,非常不利于系统维护,比如下边代码中请求系统管理服务的地址使用的是localhost
export async function dictionaryAll(params: any = undefined, body: any = undefined): Promise<ISystemDictionary[]> {//const { data } = await createAPI('/system/dictionary/all', 'get', params, body)const { data } = await createAPI('http://localhost:63110/system/dictionary/all', 'get', params, body)return data
}
当系统上线后这里需要改成公网的域名,如果这种地址非常多则非常麻烦。
基于这个问题可以采用网关来解决,如下图:
这样在前端的代码中只需要指定每个接口的相对路径,如下所示:
在前端代码的一个固定的地方在接口地址前统一加网关的地址,每个请求统一到网关,由网关将请求转发到具体的微服务。
为什么所有的请求先到网关呢?
有了网关就可以对请求进行路由,路由到具体的微服务,减少外界对接微服务的成本,比如:400电话,路由的试可以根据请求路径进行路由、根据host地址进行路由等, 当微服务有多个实例时可以通过负载均衡算法进行路由,如下:
另外,网关还可以实现权限控制、限流等功能。
项目采用Spring Cloud Gateway作为网关,网关在请求路由时需要知道每个微服务实例的地址,项目使用Nacos作用服务发现中心和配置中心,整体的架构图如下
流程如下:
1、微服务启动,将自己注册到Nacos,Nacos记录了各微服务实例的地址。
2、网关从Nacos读取服务列表,包括服务名称、服务地址等。
3、请求到达网关,网关将请求路由到具体的微服务。
要使用网关首先搭建Nacos,Nacos有两个作用:
1、服务发现中心。
微服务将自身注册至Nacos,网关从Nacos获取微服务列表。
2、配置中心。
微服务众多,它们的配置信息也非常复杂,为了提供系统的可维护性,微服务的配置信息统一在Nacos配置。
2.2 搭建Nacos
2.2.1 服务发现中心
Spring Cloud alibaba: nacos服务注册中心,配置中心
首先搭建Nacos服务发现中心。
- namespace:用于区分环境、比如:开发环境、测试环境、生产环境。
- group:用于区分项目,比如:xuecheng-plus项目、xuecheng2.0项目
1)使用sh /data/soft/restart.sh启动Nacos
2)访问:http://192.168.101.65:8848/nacos/,账号密码:nacos/nacos,首先在nacos配置namespace:
3)创建命名空间
2.2.2 完成各服务注册到Naocs
1) 在xuecheng-plus-parent中添加依赖管理
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope>
</dependency>
2)在内容管理模块的接口工程、系统管理模块的接口工程中添加如下依赖,将服务配置到nacos
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--cloud的基础环境包-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-context</artifactId>
</dependency>
3)配置nacos的地址
在系统管理的接口工程的配置文件中配置如下信息:
#微服务配置
spring:application:name: system-servicecloud:nacos:server-addr: 192.168.101.65:8848discovery:namespace: devgroup: xuecheng-plus-project
在内容管理的接口工程的配置文件中配置如下信息:
spring:application:name: content-apicloud:nacos:server-addr: 192.168.101.65:8848discovery:namespace: devgroup: xuecheng-plus-project
4)重启内容管理服务、系统管理服务。
待微服务启动成功,进入Nacos服务查看服务列表,
2.2.3 配置中心
2.2.3.1 配置三要素
搭建完成Nacos服务发现中心,下边搭建Nacos配置中心,其目的就是通过Nacos去管理项目的所有配置。
先将项目中的配置文件分分类:
1、每个项目特有的配置
是指该配置只在有些项目中需要配置,或者该配置在每个项目中配置的值不同。
比如:spring.application.name每个项目都需要配置但值不一样,以及有些项目需要连接数据库而有些项目不需要,有些项目需要配置消息队列而有些项目不需要。
2、项目所公用的配置
是指在若干项目中配置内容相同的配置。比如:redis的配置,很多项目用的同一套redis服务所以配置也一样。另外还需要知道nacos如何去定位一个具体的配置文件,即:namespace、group、dataid.
- 通过namespace、group找到具体的环境和具体的项目。
- 通过dataid找到具体的配置文件,dataid有三部分组成
比如:content-service-dev.yaml配置文件 由(content-service)-(dev). (yaml)三部分组成
content-service:第一部分,它是在application.yaml中配置的应用名,即spring.application.name的值。
dev:第二部分,它是环境名,通过spring.profiles.active指定,
Yaml: 第三部分,它是配置文件 的后缀,目前nacos支持properties、yaml等格式类型,本项目选择yaml格式类型。
所以,如果我们要配置content-service工程的配置文件:
在开发环境中配置content-service-dev.yaml
在测试环境中配置content-service-test.yaml
在生产环境中配置content-service-prod.yaml
我们启动项目中传入spring.profiles.active的参数决定引用哪个环境的配置文件,例如:传入spring.profiles.active=dev表示使用dev环境的配置文件即content-service-dev.yaml。
2.2.3.2 配置content-service
下边以开发环境为例对content-service工程的配置文件进行配置,进入nacos,进入开发环境。
新建配置
yaml配置如下:
server:servlet:context-path: /contentport: 63041spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&username: rootpassword: mysql
idea中bootstrap.yaml配置
#server:
# servlet:
# context-path: /content
# port: 63041
#微服务配置
spring:application:name: content-api #服务名 content-api-dev.yamlcloud:nacos:server-addr: 192.168.101.65:8848discovery: #服务注册相关配置namespace: dev402group: xuecheng-plus-projectconfig: #配置文件相关配置namespace: dev402group: xuecheng-plus-projectfile-extension: yamlrefresh-enabled: true# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
# username: root
# password: mysqlprofiles:active: dev #环境名
因为api接口工程依赖了service工程 的jar,所以这里使用extension-configs扩展配置文件 的方式引用service工程所用到的配置文件
1)service工程导入依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2)content-service配置文件配置如下
3)content-service的nacos配置
2.2.3.3配置content-api
service配置好了,而api又依赖于service,以相同的方法配置content-api工程的配置文件,在nacos中的开发环境中配置content-api-dev.yaml,内容如下:
在content-api工程 的本地配置bootstrap.yaml,内容如下:
注意:因为api接口工程依赖了service工程 的jar,所以这里使用extension-configs扩展配置文件 的方式引用service工程所用到的配置文件。
#server:
# servlet:
# context-path: /content
# port: 63041
#微服务配置
spring:application:name: content-api #服务名 content-api-dev.yamlcloud:nacos:server-addr: 192.168.101.65:8848discovery: #服务注册相关配置namespace: dev402group: xuecheng-plus-projectconfig: #配置文件相关配置namespace: dev402group: xuecheng-plus-projectfile-extension: yamlrefresh-enabled: trueextension-configs:- data-id: content-service-${spring.profiles.active}.yamlgroup: xuecheng-plus-projectrefresh: trueshared-configs:- data-id: swagger-${spring.profiles.active}.yamlgroup: xuecheng-plus-commonrefresh: true- data-id: logging-${spring.profiles.active}.yamlgroup: xuecheng-plus-commonrefresh: true# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
# username: root
# password: mysqlprofiles:active: dev #环境名#logging:
# config: classpath:log4j2-dev.xml # 日志文件配置路径#swagger:
# title: "学成在线内容管理系统"
# description: "内容系统管理系统对课程相关信息进行管理"
# base-package: com.xuecheng.content
# enabled: true
# version: 1.0.0
2.2.4 公用配置
nacos提供了shared-configs可以引入公用配置。
在content-api中配置了swagger,所有的接口工程 都需要配置swagger,这里就可以将swagger的配置定义为一个公用配置,哪个项目用引入即可。
单独在xuecheng-plus-common分组下创建xuecheng-plus的公用配置,进入nacos的开发环境,添加swagger-dev.yaml公用配置
- swagger配置
- 日志配置
- 在api工程yml文件中引用
2.2.5 配置优先级
引入配置文件的形式有:
1、以项目应用名方式引入
2、以扩展配置文件方式引入
3、以共享配置文件 方式引入
4、本地配置文件
各配置文件 的优先级:项目应用名配置文件 > 扩展配置文件 > 共享配置文件 > 本地配置文件
有时候我们在测试程序时直接在本地加一个配置进行测试,比如下边的例子:
我们想启动两个内容管理微服务,此时需要在本地指定不同的端口,通过VM Options参数,在IDEA配置启动参数
启动ContentApplication2,发现端口仍然是63040,这说明本地的配置没有生效。
这时我们想让本地最优先,可以在nacos配置文件 中配置如下即可实现:
#配置本地优先
spring:cloud:config:override-none: true
再次启动ContentApplication2,端口为63041
2.2.5 导入配置文件
2.3 搭建网关
- 新建一个网关工程
- 添加依赖
<parent><groupId>com.xuecheng</groupId><artifactId>xuecheng-plus-parent</artifactId><version>0.0.1-SNAPSHOT</version><relativePath>../xuecheng-plus-parent</relativePath>
</parent>
<artifactId>xuecheng-plus-gateway</artifactId><dependencies><!--网关--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--服务发现中心--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- 排除 Spring Boot 依赖的日志包冲突 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><!-- Spring Boot 集成 log4j2 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency></dependencies>
- 配置网关的bootstrap.yaml配置文件
#微服务配置
spring:application:name: gatewaycloud:nacos:server-addr: 192.168.101.65:8848discovery:namespace: devgroup: xuecheng-plus-projectconfig:namespace: devgroup: xuecheng-plus-projectfile-extension: yamlrefresh-enabled: trueshared-configs:- data-id: logging-${spring.profiles.active}.yamlgroup: xuecheng-plus-commonrefresh: trueprofiles:active: dev
-
在nacos上配置网关路由策略
server:port: 63010 # 网关端口
spring:cloud:gateway:
# filter:
# strip-prefix:
# enabled: trueroutes: # 网关路由配置- id: content-api # 路由id,自定义,只要唯一即可# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址uri: lb://content-api # 路由的目标地址 lb就是负载均衡,后面跟服务名称predicates: # 路由断言,也就是判断请求是否符合路由规则的条件- Path=/content/** # 这个是按照路径匹配,只要以/content/开头就符合要求
# filters:
# - StripPrefix=1- id: system-api# uri: http://127.0.0.1:8081uri: lb://system-apipredicates:- Path=/system/**
# filters:
# - StripPrefix=1- id: media-api# uri: http://127.0.0.1:8081uri: lb://media-apipredicates:- Path=/media/**
# filters:
# - StripPrefix=1- id: search-service# uri: http://127.0.0.1:8081uri: lb://searchpredicates:- Path=/search/**
# filters:
# - StripPrefix=1- id: auth-service# uri: http://127.0.0.1:8081uri: lb://auth-servicepredicates:- Path=/auth/**
# filters:
# - StripPrefix=1- id: checkcode# uri: http://127.0.0.1:8081uri: lb://checkcodepredicates:- Path=/checkcode/**
# filters:
# - StripPrefix=1- id: learning-api# uri: http://127.0.0.1:8081uri: lb://learning-apipredicates:- Path=/learning/**
# filters:
# - StripPrefix=1- id: orders-api# uri: http://127.0.0.1:8081uri: lb://orders-apipredicates:- Path=/orders/**
# filters:
# - StripPrefix=1
启动网关工程,通过网关工程访问微服务进行测试。