学成在线借鉴了MOOC(大型开放式网络课程,即MOOC(massiveopenonlinecourses))的设计思想,是一个提供IT职业课程在线学习的平台,它为即将和已经加入IT领域的技术人才提供在线学习服务,用户通过在线学习、在线练习、在线考试等学习内容,最终掌握所学的IT技能,并能在工作中熟练应用。当前市场的在线教育模式多种多样,包括:B2C、C2C、B2B2C等业务模式,学成在线采用B2B2C业务模式,即向企业或个人提供在线教育平台和学生完成教学活动,市场上类似的平台有:网易云课堂、腾讯课堂等,学成在线的特点是IT职业课程在线教学。
学成在线是一个在线教育平台,提供IT职业课程在线学习,平台包括:门户、学习中心、教学管理中心、系统管理中心、社交系统等子系统。
项目的功能架构如下图:
项目采用前后端分离的技术架构,前端采用vue.js技术栈,服务端采用SpringBoot、SpringCloud等Spring全家桶技术栈。具体见问题2.
项目采用前后端分离的技术架构,前端采用vue.js构建,服务端采用SpringCloud微服务架构,系统分为用户层、CDN、负载均衡、前端UI、微服务层、数据层、接口层及DevOps等部分组成,下图是完整的技术架构图:
业务流程举例:
1、用户可以通过pc、手机等客户端访问系统进行在线学习。2、系统应用CDN技术,对一些图片、CSS、视频等资源从CDN调度访问。3、所有的请求全部经过负载均衡器。4、对于PC、H5等客户端请求,首先请求UI层,渲染用户界面。5、客户端UI请求服务层获取进行具体的业务操作。6、服务层将数据持久化到数据库。
下图是技术架构简图:
1、用户层用户层描述了本系统所支持的客户端用户有哪些,本项目目前为各用户提供服务,包括H5、PC、Android和IOS等。2CDN全称ContentDeliveryNetwork,即内容分发网络,本系统所有静态资源全部通过CDN加速来提高访问速度。系统静态资源包括:html页面、js文件、css文件、image图片、pdf和ppt及doc教学文档、video视频等。
7DevOps提供了本系统开发、运营、维护支撑的系统,包括如下内容:Eureka服务治理中心:提供服务治理服务,包括:服务注册、服务获取等。Docker容器化部署服务:将本系统所有服务采用容器化部署方式。Maven项目管理工具:提供管理项目所有的Java包依赖、项目工程打包服务。Git/GitLab代码管理服务:提供git代码管理服务。SpringBootAdmin服务健康监控:监控微服务的健康状态、会话数量、并发数等。
所有微服务基于SpringBoot、SpringCloud构建1)控制层:SpringMVC、SpringSecurityOauth2、Swagger2)业务层:事务控制:Spring任务处理:SpringTask数据缓存:SpringDataRedis消息队列:SpringRabbitTemplate搜索:Elasticsearch3)持久层:操作MySQL:MyBatis、com.alibaba.druid(采用druid-spring-boot-starter)SpringDataJpa操作MongoDB:SpringDataMongodb4)数据层,采用MySQL和MongoDb存储数据,MySQL存储用户、课程等系统核心信息,MongoDb存储cms、配置信息等。
项目架构设立接口层,接口层使用swagger注解描述接口的内容,接口定义规范如下:1、请求get请求时,前端请求key/value串,SpringMVC采用基本数据类型(String、Integer等)或自定义类型接收。Post请求时,前端请Form表单数据(application/x-www-form-urlencoded)和Json数据(Content-Type=application/json)、多部件类型数据(multipart/form-data),对于Json数据SpringMVC使用@RequestBody注解解析请求的json数据。2、响应响应结果统一信息为:是否成功、操作代码、提示信息及自定义数据。响应结果统一格式为json。
两台EurekaServer互相注册,组成高可用。微服务向EurekaServer注册自己,并在远程调用时从微服务发现目标服务地址。
微服务远程调用采用客户端负载均衡技术,使用FeignClient。
网关的作用是负载均衡、路由转发、请求过虑等。项目中网关与Nginx配合使用。
项目是基于Spring进行构建的:
1、所有的微服务开发采用SpringBoot开发2、数据层使用SpringDataJPA、SpringDataMongoDB、SpringDataredis。3、业务层使用Spring来控制本地事务,还使用了SpringTask任务调度框架、SpringAMQP组件等。4、控制层使用SpringMVC、SprnigSecurityOauth2。5、微服务管理使用SpringCloud的Eureka注册中心,微服务之间调用使用Ribbon和FeignClient完成。6、使用Zuul网关完成微服务安全验证
项目中使用SpringDataJPA和MyBatis都是用来访问MySQL,但是它们的分工不同:SpringDataJPA是Spring提供的一套JPA接口,使用SpringDataJPA主要完成一些简单的增、删、改、查功能。对于复杂的查询功能会使用MyBatis编写SQL语言来实现,因为使用SpringDataJPA来做一些复杂的查询是没有MyBatis方便的,SpringDataJPA是面向的对象,而MyBatis直接面向SQL语句。
容错保护是指微服务在执行过程中出现错误并从错误中恢复的能力。微服务容错性不好很容易导致雪崩效应,什么是雪崩效应?
SpringCloudHystrix是基于Netflix的开源框架Hystrix的整合,它实现了断路保护、线程隔离、信号隔离等容错功能。断路保护:
具体的操作方法可以采用Fallback,会每个FeignClient方法调用Fallback,当出现开路则调用Fallback方法返回错误结果。
线程隔离:调用微服务使用不同的线程池,线程池之间互不影响,即使某个服务不可用也不影响其它服务的调用,比如:对商品服务的调用使用一个线程池,对用户服务的调用使用另一个线程池,即使用户服务不可用也不影响商品服务的调用。
1、视图层在前端和服务端都存在。2、前端视图采用vue.js+elementUI产品界面。3、服务端都是暴露的rest接口,统一用json展示数据。
本问题考察前后端分离开发中接口定义技能。
1、接口定义
使用SpringMVC编写Controller方法,对外暴露Http接口,在Controller方法上使用RequestMapping、PostMapping、GetMapping等注解定义Http接口。
2、采用什么数据格式?分别说明请求和响应:请求:get请求时,前端请求key/value串,SpringMVC采用基本数据类型(String、Integer等)或自定义类型接收。Post请求时,前端请Form表单数据(application/x-www-form-urlencoded)和Json数据(Content-Type=application/json)、多部件类型数据(multipart/form-data),对于Json数据SpringMVC使用@RequestBody注解解析请求的json数据。响应:统一响应json格式。
3、如何实现的?json格式数据SpringMVC采用FastJson解析为对象。非json格式数据SpringMVC提供参数绑定的方法,将key/value或Form-Data数据转换为对象或基本数据类型的变量。
1、前端与后端开发人员讨论确定接口。接口讨论通过,形成接口文档。本项目专门设立一个api工程,在此工程定义接口,SpringBoot集成Swagger,生成Swagger接口,前后端开发人员通过html查看接口文档的内容。2、前端与后端开发人员按照接口文档进行开发。开发过程中各自进行单元测试。
3、双方功能开发完成进行前后端联调。
前端工程大多为单页面应用(SPA),采用vue.js框架开发,搜索功能前端采用nuxt.js服务端渲染(SSR)框架开发。技术栈包括:1、node.js2、vue.js3、npm/cnpm4、webpack5、axios6、nuxt.js
CMS即内容管理系统,本项目对CMS系统的定位是对各各网站(子站点)页面的管理,本项目的CMS系统不去管理每个子网站的全部资源,比如:图片、CSS、html页面等,主要管理由于运营需要而经常变动的页面,从而满足根据运营需要快速开发、上线的需求。功能包括:1、站点管理,站点就是本项目各各子网站,站点信息包括:站点名称、站点域名、端口、服务器物理路径等。2、模板管理,由于要对页面进行静态化,使用freemarker引擎技术,所以需要定义模板。3、页面管理,包括:页面添加、页面修改、页面删除等操作。4、页面预览,对页面静态化,在浏览器预览页面静态化内容。5、页面发布,将页面静态化后发布到所属站点服务器。
使用方法是:使用Springdatamongodb包下提供的GridFsTemplate访问GirdFS。
1、平台包括多个站点,页面归属不同的站点,需求是发布一个页面应将该页面发布到所属站点的服务器上。2、每个站点服务部署CMSClient程序,并与交换机绑定,绑定时指定站点Id为routingKey。指定站点id为routingKey就可以实现cmsclient只能接收到所属站点的页面发布消息。3、页面发布程序向MQ发布消息时指定页面所属站点Id为routingKey,根据routingKey将消息发给指定的CMSClient。
每次发布会在数据库记录发布日志,每个CMSClient完成页面发布会上报发布结果。1、在站点管理中配置了每个站点的服务器信息2、在每次发布页面时会记录发布日志(服务器ID、页面ID、页面名称、发布结果)3、CMSClient完成页面发布后会向数据上报发布结果。4、用户通过查询发布日志表的信息就可以知道每一次的发布结果(哪些服务器页面发布成功,哪些发布失败)。
1、课程信息比较复杂,为了方便教学机构按步骤管理课程信息,并且也可以划分权限管理课程信息,将课程信息管理功能分为课程基本信息管理、课程图片管理、课程营销信息管、课程计划管理等模块。2、将课程信息分开也是为了系统扩展需要,如果将课程所有信息存储在一张表中将不利于系统扩展。
见问题“图片服务器”。
每个教学机构都可以在媒资系统管理自己的教学资源,包括:视频、教案等文件。媒资管理的主要管理对象是课程录播视频,包括:媒资文件的查询、视频上传、视频删除、视频处理等。媒资查询:教学机构查询自己所拥有的媒体文件。视频上传:将用户线下录制的教学视频上传到媒资系统。视频处理:视频上传成功,系统自动对视频进行编码处理。视频删除:如果该视频已不再使用,可以从媒资系统删除。
前端使用WebUploader将文件分块,调用服务端分块上传接口上传分块文件,分块上传完毕前端请求服务端进行合并,当上传过程中断再次进行上传时服务端判断分块是否已经上传,已经上传的分块不再重新上传。
上图所示,Java程序调用ffmpeg及流媒体程序员提供的视频处理类库(C程序)完成avi、mp4视频转成m3u8格式的视频。Java程序使用Jdk提供的ProcessBuilder调用ffmpeg及C程序进行视频处理。ProcessBuilder可以调用第三方程序,在java程序运行时启动第三方程序进程。视频处理完成,Java程序捕获第三方程序的输出日志,解析出视频处理完成标记,更新视频处理状态为已完成。
视频处理完成会在中心媒体服务器保存一份,另外通过CDN程序将视频发布到边缘媒体服务器,用户点播视频通过CDN请求边缘媒体服务器中的视频,提高了视频播放速度。具体使用的是第三方公司的CDN服务。
本项目采用fastDFS分布式系统作为图片服务器。FastDFS是用c语言编写的一款开源的分布式文件系统,适合小文件的存储。FastDFS包括Trackerserver和Storageserver。客户端请求Trackerserver进行文件上传、下载,通过Trackerserver调度向Storageserver完成文件上传和下载。使用FastDSF官方提供的JavaAPI实现。图片服务使用Nginx作为代理服务器,对Storage上部署的Nginx完成负载均衡请求。
FastDFS相比其它的分布式文件系统它适用小文件存储,它不对文件进行分块存储,也不用对文件进行合并处理,所以性能比GFS、HDFS等通用文件系统的性能要高。
执行流程如下:
1、管理员进入教学管理前端,点击上传图片2、图片上传至文件系统服务,文件系统请求fastDFS上传文件3、文件系统将文件入库,存储到文件系统服务数据库中。4、文件系统服务向前端返回文件上传结果,如果成功则包括文件的Url路径。5、课程管理前端请求课程管理进行保存课程图片信息到课程数据库。6、课程管理服务将课程图片保存在课程数据库。
FastDFS支付断点续传,在Api中有append_file1方法就是用来实现断点续传的,本项目没有使用FastDFS的断点续传功能。
1、接口的开发需要前端和服务端共同调试,要仔细阅读测试人员反映的bug信息,判断这个bug是服务端的bug还是前端的bug。通常服务接口开发完成会使用postman工具进行测试,测试没有问题再提交到Git或SVN。2、找到bug的出错点就可以根据bug信息进行修改。3、修改完成需要前后端再次连调测试,按照测试人员提交的测试流程重新进行测试,测试通过将此bug置为已解决。
根据自己的实际情况回答开发中遇到的问题:例子:接口参数的签名问题,当时是因为自己没有仔细看接口文档导致少写一个必填参数一直报签名失败,随后将所有必填参数填写完成,最终解决问题。
系统对异常的处理使用统一的异常处理流程。1、自定义异常类型。2、自定义错误代码及错误信息。3、对于可预知的异常由程序员在代码中主动抛出自定义异常类型的异常,抛出异常时需要指定错误代码。4、对于不可预知的异常(运行时异常)由SpringMVC统一捕获Exception类型的异常,由统一的异常捕获类来解析处理,并转换为与自定义异常类型一致的信息格式(错误代码+错误信息)。5、可预知的异常及不可预知的运行时异常最终会采用统一的信息格式(错误代码+错误信息)来表示,最终也会随请求响应给客户端。
项目使用RabbitMQ消息队列。RabbitMQ提供很多的工作模式,如下:1、Workqueues2、Publish/Subscribe3、Routing4、Topics5、Header6、RPC项目主要使用了Routing模式。Routing模式即路由模式,使用方法是:1、每个消费者监听自己的队列,并且设置routingkey。2、生产者将消息发给交换机,由交换机根据routingkey来转发消息到指定的队列。
有哪些应用场景?
本项目采用HLS技术实现视频点播。1、使用FFmpeg对视频进行编码处理,生成m3u8文件及ts文件。2、使用Nginx作为媒体服务器。3、客户端使用video.js播放视频。
例子:在处理订单时要用到定时任务,当时采用的是SpringTask来完成,由于一个订单服务会部署多个,多个订单服务同时去处理任务会造成任务被重复处理的情况,如何解决任务的重复处理。解决:采用乐观锁解决,在任务表中设置一个version字段记录版本号,取出任务记录同时拿到任务的版本号,执行前对任务进行锁定,具体的做法是执行update根据当前版本号将版本号加1,update成功表示锁定任务成功,即可开始执行任务。
大概花了一个多月来做这个项目,感触很深,了解了微服务在企业的开发流程,从需求分析丶环境搭建丶数据库设计丶服务端开发丶前端丶测试丶部署等流程。虽然这个项目是2018年的,但很多技术都不算落后,用来做为微服务项目经验足以。做这个项目也遇到很多bug,明明按照视频文档一步一步的做,有时得不到自己想要的结果,然后就不停的调试,卸载重装。一个问题可能做一下午也解决不了,有时会崩溃,这时候就做其他事情分散注意力,比如洗个澡清醒一下再战。不要灰心丧气,急躁,当你解决了的就会有成就感,即使解决不了也尽力了。这就是我们程序员的代码精神吧。