學成在線借鑑了MOOC(大型開放式網絡課程,即MOOC(massive open online courses))的設計思想,是一
個提供IT職業課程在線學習的平臺,它爲即將和已經加入IT領域的技術人才提供在線學習服務,用戶經過在線學
習、在線練習、在線考試等學習內容,最終掌握所學的IT技能,並能在工做中熟練應用。
當前市場的在線教育模式多種多樣,包括:B2C、C2C、B2B2C等業務模式,學成在線採用B2B2C業務模式,即向
企業或我的提供在線教育平臺和學生完成教學活動,市場上相似的平臺有:網易雲課堂、騰訊課堂等,學成在線的
特色是IT職業課程在線教學。css
學成在線是一個在線教育平臺,提供IT職業課程在線學習,平臺包括:門戶、學習中心、教學管理中心、系統管理
中心、社交系統等子系統。html
項目的功能架構以下圖:前端
門戶是整個平臺的入口,功能包括:門戶首頁、註冊/登陸、課程搜索、職業規劃,客服等。
學習中心爲用戶提供在線學習服務,包括:個人課程、視頻點播、視頻直播、在線考試、在線答疑、學習統計等功
能;
教學管理中心爲教育機構或我的講師提供教學管理功能,包括:課程管理、媒資管理、考試管理、問答管理等功
能;
系統管理中心提供系統參數配置、CMS、數據字典、分類管理等功能。vue
項目採用先後端分離的技術架構,前端採用vue.js技術棧,服務端採用SpringBoot、SpringCloud等Spring全家桶
技術棧。
具體見問題2.java
項目採用先後端分離的技術架構,前端採用vue.js構建,服務端採用Spring Cloud微服務架構,系統分爲用戶層、
CDN、負載均衡、前端UI、微服務層、數據層、接口層及DevOps等部分組成,下圖是完整的技術架構圖:node
業務流程舉例:webpack
1 、用戶能夠經過pc、手機等客戶端訪問系統進行在線學習。
二、 系統應用CDN技術,對一些圖片、CSS、視頻等資源從CDN調度訪問。
三、全部的請求所有通過負載均衡器。
四、對於PC、H5等客戶端請求,首先請求UI層,渲染用戶界面。
五、客戶端UI請求服務層獲取進行具體的業務操做。
六、服務層將數據持久化到數據庫。ios
下圖是技術架構簡圖:git
一、用戶層
用戶層描述了本系統所支持的客戶端用戶有哪些,本項目目前爲各用戶提供服務,包括H五、PC、Android和IOS
等。
2 CDN全稱Content Delivery Network,即內容分發網絡,本系統全部靜態資源所有經過CDN加速來提升訪問速
度。系統靜態資源包括:html頁面、js文件、css文件、image圖片、pdf和ppt及doc教學文檔、video視頻等。程序員
3 負載均衡 系統的CDN層、UI層、服務層及數據層均設置了負載均衡服務,系統採用LVS+Nginx實現負載均衡均
衡。
4 UI層 UI層描述了系統向pc用戶、app用戶、h5用戶提供的產品界面。本項目在PC和H5端採用vue.js+elementUI
實現。
5 微服務層將系統服務分類三類:前端服務、後端服務及系統服務。 前端服務:主要爲學習用戶提供學習服務。
後端服務:主要爲管理用戶提供教學管理服務。 系統服務:公共服務,爲系統的全部微服務提供公共服務功能。
6 外部系統接口 包括以下接口:
1)第三方登陸接口,如QQ、微博、微信等。 2)支付寶、微信支付接口 3)短信接口 (阿里大於)4)郵件接
口,經過smpt郵件服務器對外發送電子郵件。 5)微信公衆號 6)點播、直播。 7)OSS存儲 8)CDN,使用最裏
雲CDN服務加速視頻訪問速度。
7 DevOps提供了本系統開發、運營、維護支撐的系統,包括以下內容:
Eureka服務治理中心:提供服務治理服務,包括:服務註冊、服務獲取等。
Docker容器化部署服務:將本系統全部服務採用容器化部署方式。
Maven項目管理工具:提供管理項目全部的Java包依賴、項目工程打包服務。
Git/GitLab代碼管理服務:提供git代碼管理服務。
Spring Boot Admin服務健康監控:監控微服務的健康狀態、會話數量、併發數等。
全部微服務基於Spring Boot、Spring Cloud構建
1)控制層:
Spring MVC、Spring Security Oauth2 、Swagger
2)業務層:
事務控制:Spring
任務處理:Spring Task
數據緩存:Spring Data Redis
消息隊列:Spring RabbitTemplate
搜索: Elasticsearch
3) 持久層:
操做MySQL:MyBatis、com.alibaba.druid(採用druid-spring-boot-starter)Spring Data Jpa
操做MongoDB:Spring Data Mongodb
4) 數據層,採用MySQL和MongoDb存儲數據,MySQL存儲用戶、課程等系統核心信息,MongoDb存儲
cms、配置信息等。
項目架構設立接口層,接口層使用swagger註解描述接口的內容,接口定義規範以下:
一、請求
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。
兩臺Eureka Server互相註冊,組成高可用。
微服務向Eureka Server註冊本身,並在遠程調用時從微服務發現目標服務地址。
微服務遠程調用採用客戶端負載均衡技術,使用Feign Client。
網關的做用是負載均衡、路由轉發、請求過慮等。
項目中網關與Nginx配合使用。
項目是基於Spring進行構建的:
1 、全部的微服務開發採用Spring Boot開發
二、數據層使用Spring Data JPA、Spring Data MongoDB、Spring Data redis。
三、業務層使用Spring來控制本地事務,還使用了Spring Task任務調度框架、Spring AMQP組件等。
四、控制層使用SpringMVC、Sprnig Security Oauth2。
五、微服務管理使用Spring Cloud的Eureka註冊中心,微服務之間調用使用Ribbon和Feign Client完成。
六、使用Zuul網關完成微服務安全驗證
一、每一個微服務使用Spring Boot開發,每一個微服務工程包括了web、service、dao三層,這和開發通常的項目沒有
區別:
a、web層使用Spring MVC實現,對外暴露API接口給前端調用。
b、service層就是根據業務邏輯編寫JavaBean,並使用Spring的聲明式事務控制方式來控制事務。
c、dao層就是數據訪問接口,來訪問MySQL和Mongodb,訪問MySQL使用Spring Data JPA和Mybatis,訪問
mongodb使用Spring data mongodb。
二、微服務開發完成要向Eureka註冊中心註冊,以便被其它微服務查找和訪問。
三、微服務與微服務之間使用feign來調用,feign Client具備負載均衡的做用。只須要在接口上聲明@FeignClient注
解,Spring底層會產生動態代理對象,使用ribbon客戶端完成調用。
四、前端訪問微服務須要經過網關,網關使用Nginx和Zuul來實現,Nginx是最前邊的負載均衡,經過Nginx以後便
到達了Zuul,項目中Zuul的功能是過慮用戶請求,判斷用戶身份,對於一些對外公開的微服務則須要通過Zuul,直
接經過Nginx負載均衡便可訪問。
項目中使用Spring Data JPA和MyBatis都是用來訪問MySQL,可是它們的分工不一樣:
Spring Data JPA是Spring 提供的一套JPA接口,使用Spring Data JPA主要完成一些簡單的增、刪、改、查功能。
對於複雜的查詢功能會使用MyBatis編寫SQL語言來實現,由於使用Spring Data JPA來作一些複雜的查詢是沒有
MyBatis方便的,Spring Data JPA是面向的對象,而MyBatis直接面向SQL語句。
容錯保護是指微服務在執行過程當中出現錯誤並從錯誤中恢復的能力。微服務容錯性很差很容易致使雪崩效應,什麼
是雪崩效應?
微服務的雪崩效應表如今服務與服務之間調用,當其中一個服務沒法提供服務可能致使其它服務也死掉,好比:單
點登陸服務調用用戶信息服務查詢用戶信息,因爲用戶信息服務沒法提供服務致使單點登陸服務一直等待,從而導
致用戶登陸、用戶退出功能沒法使用,像這樣由一個服務所引發的一連串的多個服務沒法提供服務便是微服務的雪
崩效應。
Spring Cloud Hystrix 是基於Netflix的開源框架Hystrix的整合,它實現了斷路保護、線程隔離、信號隔離等容錯
功能。
斷路保護:
斷路保護就相似家庭電路中的保險絲,當電路過載時保險絲會自動切斷,保護整個電路的安全。微服務的斷路保護
的工做原理是當請求微服務失敗的數量達到必定比例時會切換爲開路狀態,當請求微服務時就直接返回結果再也不請
求微服務,當保持開路狀態一段時間後判斷微服務是否能夠正常請求,若是正常則切換到半開路狀態,最後切換到
哪閉路狀態。
具體的操做方法能夠採用 Fallback,會每一個FeignClient方法調用Fallback,當出現開路則調用Fallback方法返回錯
誤結果。
線程隔離:
調用微服務使用不一樣的線程池,線程池之間互不影響,即便某個服務不可用也不影響其它服務的調用,好比:對商
品服務的調用使用一個線程池,對用戶服務的調用使用另外一個線程池,即便用戶服務不可用也不影響商品服務的調
用。
一、視圖層在前端和服務端都存在。
二、前端視圖採用vue.js+elementUI產品界面。
三、服務端都是暴露的rest接口,統一用json展現數據。
本問題考察先後端分離開發中接口定義技能。
一、接口定義
使用 SpringMVC編寫Controller方法,對外暴露Http接口,在Controller方法上使用RequestMapping、
PostMapping、GetMapping等註解定義Http接口。
二、採用什麼數據格式?
分別說明請求和響應:
請求:
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格式。
三、如何實現的?
json格式數據SpringMVC採用FastJson解析爲對象。
非json格式數據SpringMVC提供參數綁定的方法,將key/value或Form-Data數據轉換爲對象或基本數據類型的變
量。
一、前端與後端開發人員討論肯定接口。
接口討論經過,造成接口文檔 。
本項目專門設立一個api工程,在此工程定義接口,Spring Boot 集成Swagger,生成Swagger接口,先後端 開發
人員經過html查看接口文檔的內容。
二、前端與後端開發人員按照接口文檔進行開發。
開發過程當中各自進行單元測試。
三、雙方功能開發完成進行先後端聯調。
前端工程大多爲單頁面應用(SPA),採用vue.js框架開發,搜索功能前端採用nuxt.js服務端渲染(SSR)框架開
發。
技術棧包括:
一、node.js
二、vue.js
三、npm/cnpm
四、webpack
五、axios
六、nuxt.js
CMS 即內容管理系統,本項目對CMS系統的定位是對各各網站(子站點)頁
面的管理,本項目的CMS系統不去管理每一個子網站的所有資源,好比:圖片、CSS、html頁面等,主要管理因爲運
營須要而常常變更的頁面,從而知足根據運營須要快速開發、上線的需求。
功能包括:
一、站點管理,站點就是本項目各各子網站,站點信息包括:站點名稱、站點域名、端口、服務器物理路徑等。
二、模板管理,因爲要對頁面進行靜態化,使用freemarker引擎技術,因此須要定義模板。
三、頁面管理,包括:頁面添加、頁面修改、頁面刪除等操做。
四、頁面預覽,對頁面靜態化,在瀏覽器預覽頁面靜態化內容。
五、頁面發佈,將頁面靜態化後發佈到所屬站點服務器。
GridFS是MongoDB提供的用於持久化存儲文件的模塊,它能夠做爲分佈式文件系統使用,CMS子系統將頁面文
件、模板文件存儲到GridFS中,因爲本項目使用MongoDB,選用GridFS能夠快速集成開發。
它的工做原理是:
在GridFS存儲文件是將文件分塊存儲,文件會按照256KB的大小分割成多個塊進行存儲,GridFS使用兩個集合
(collection)存儲文件,一個集合是chunks, 用於存儲文件的二進制數據;一個集合是files,用於存儲文件的元數
據信息(文件名稱、塊大小、上傳時間等信息)。
從GridFS中讀取文件要對文件的各各塊進行組裝、合併。
使用方法是:
使用Spring data mongodb包下提供的GridFsTemplate訪問GirdFS。
gridFsTemplate.findone() 查詢文件 gridFsTemplate.delete() 刪除文件 gridFsTemplate.store()存儲文件
一、平臺包括多個站點,頁面歸屬不一樣的站點,需求是發佈一個頁面應將該頁面發佈到所屬站點的服務器上。
二、每一個站點服務部署CMS Client程序,並與交換機綁定,綁定時指定站點Id爲routingKey。
指定站點id爲routingKey就能夠實現cms client只能接收到所屬站點的頁面發佈消息。
三、頁面發佈程序向MQ發佈消息時指定頁面所屬站點Id爲routingKey,根據routingKey將消息發給指定的
CMS Client。
每次發佈會在數據庫記錄發佈日誌,每一個CMS Client完成頁面發佈會上報發佈結果。
一、在站點管理中配置了每一個站點的服務器信息
二、在每次發佈頁面時會記錄發佈日誌(服務器ID、頁面ID、頁面名稱、發佈結果)
三、CMS Client完成頁面發佈後會向數據上報發佈結果。
四、用戶經過查詢發佈日誌表的信息就能夠知道每一次的發佈結果(哪些服務器頁面發佈成功,哪些發佈失敗)。
一、課程信息比較複雜,爲了方便教學機構按步驟管理課程信息,而且也能夠劃分權限管理課程信息,將課程信息
管理功能分爲課程基本信息管理、課程圖片管理、課程營銷信息管、課程計劃管理等模塊。
二、將課程信息分開也是爲了系統擴展須要,若是將課程全部信息存儲在一張表中將不利於系統擴展。
見問題「圖片服務器」。
每一個教學機構均可以在媒資系統管理本身的教學資源,包括:視頻、教案等文件。
媒資管理的主要管理對象是課程錄播視頻,包括:媒資文件的查詢、視頻上傳、視頻刪除、視頻處理等。
媒資查詢:教學機構查詢本身所擁有的媒體文件。
視頻上傳:將用戶線下錄製的教學視頻上傳到媒資系統。
視頻處理:視頻上傳成功,系統自動對視頻進行編碼處理。
視頻刪除 :若是該視頻已再也不使用,能夠從媒資系統刪除。
前端使用WebUploader將文件分塊,調用服務端分塊上傳接口上傳分塊文件,分塊上傳完畢前端請求服務端進行
合併,當上傳過程當中斷再次進行上傳時服務端判斷分塊是否已經上傳,已經上傳的分塊再也不從新上傳。
上圖所示,Java程序調用ffmpeg及流媒體程序員提供的視頻處理類庫(C程序)完成avi、mp4視頻轉成m3u8格式
的視頻。
Java程序使用Jdk提供的Process Builder調用ffmpeg及C程序進行視頻處理。
Process Builder能夠調用第三方程序,在java程序運行時啓動第三方程序進程。
視頻處理完成,Java程序捕獲第三方程序的輸出日誌,解析出視頻處理完成標記,更新視頻處理狀態爲已完成。
視頻處理完成會在中心媒體服務器保存一份,另外經過CDN程序將視頻發佈到邊緣媒體服務器,用戶點播視頻通
過CDN請求邊緣媒體服務器中的視頻,提升了視頻播放速度。
具體使用的是第三方公司的CDN服務。
項目中課程搜索採用ElasticSearch來完成。
實現方法是:
1、使用 Logstash(logstash是ES下的一款開源軟件,它可以同時 從多個來源採集數據、轉換數據)將MySQL中
的課程信息讀取到ES中建立索引,使用IK分詞器進行分詞。
二、使用 Java High Level REST Client完成搜索。
三、生產環境使用ES部署爲集羣。
本項目採用fastDFS分佈式系統做爲圖片服務器。
FastDFS是用c語言編寫的一款開源的分佈式文件系統,適合小文件的存儲。
FastDFS包括 Tracker server和Storageserver。客戶端請求Tracker server進行文件上傳、下載,經過Tracker
server調度向Storage server完成文件上傳和下載。
使用FastDSF官方提供的Java API實現。
圖片服務使用Nginx做爲代理服務器,對Storage上部署的Nginx完成負載均衡請求。
FastDFS相比其它的分佈式文件系統它適用小文件存儲,它不對文件進行分塊存儲,也不用對文件進行合併處理,
因此性能比GFS、HDFS等通用文件系統的性能要高。
執行流程以下:
1 、管理員進入教學管理前端,點擊上傳圖片
二、圖片上傳至文件系統服務,文件系統請求fastDFS上傳文件
三、文件系統將文件入庫,存儲到文件系統服務數據庫中。
四、文件系統服務向前端返回文件上傳結果,若是成功則包括文件的Url路徑。
五、課程管理前端請求課程管理進行保存課程圖片信息到課程數據庫。
六、課程管理服務將課程圖片保存在課程數據庫。
FastDFS支付斷點續傳,在Api中有append_file1方法就是用來實現斷點續傳的,本項目沒有使用FastDFS的斷點續
傳功能。
本項目採用 Spring security + Oauth2完成用戶認證及用戶受權。認證受權流程以下:
一、用戶請求認證服務完成身份認證。
二、認證服務下發用戶身份令牌和JWT令牌,擁有身份令牌表示身份合法,Jwt令牌用於完成受權。
三、用戶攜帶jwt令牌請求資源服務。
四、網關校驗用戶身份令牌的合法,不合法表示用戶沒有登陸,若是合法則放行繼續訪問。
五、資源服務獲取jwt令牌,根據jwt令牌完成受權。
一、在微服務中使用Spring 聲明式事務控制方式進行控制,在Service方法上添加@Transctional註解便可實現事務
控制,它控制的是MySQL的本地事務。
二、項目中大量存在分佈式事務控制,好比下單支付、課程發佈等地址都用到了分佈式事務。
本項目實現分佈式事務控制實現最終數據一致性,作法是:
a、將分佈式事務拆分爲多個本地事務。
b、提交事務前每一個參與者要經過數據校驗,和資源預留。
c、由消息隊列去通知多個事務參與者完成本地事務的提交。
d、提交失敗的本地事務會重試。
一、接口的開發須要前端和服務端共同調試,要仔細閱讀測試人員反映的bug信息,判斷這個bug是服務端的bug還
是前端的bug。一般服務接口開發完成會使用postman工具進行測試,測試沒有問題再提交到Git或SVN。
二、找到bug的出錯點就能夠根據bug信息進行修改。
三、修改完成須要先後端再次連調測試,按照測試人員提交的測試流程從新進行測試,測試經過將此bug置爲已解
決。
若是作過支付接口則要回答實現過程:
一、系統中收費的課程須要用戶在線支付,支付接口採用微信的掃碼支付。
2 、拿到需求後,肯定使用微信支付,首先去閱讀微信的接口文檔,這裏重點閱讀統一下單、支付結果通知、支付
結果查詢三個接口。
三、下載官方提供的sdk編寫單元測試用例測試每一個接口。測試時沒有使用微信的沙箱測試,直接使用正式接口,我
們將金額改的小一些進行測試。
四、單元測試經過後開發整個支付功能,最終集成測試經過。
根據本身的實際狀況回答開發中遇到的問題:
例子:
接口參數的簽名問題,當時是由於本身沒有仔細看接口文檔致使少寫一個必填參數一直報簽名失敗,隨後將全部必
填參數填寫完成,最終解決問題。
系統對異常的處理使用統一的異常處理流程。
一、自定義異常類型。
二、自定義錯誤代碼及錯誤信息。
三、對於可預知的異常由程序員在代碼中主動拋出自定義異常類型的異常,拋出異常時須要指定錯誤代碼。
四、對於不可預知的異常(運行時異常)由SpringMVC統一捕獲Exception類型的異常,由統一的異常捕獲類來解析
處理,並轉換爲與自定義異常類型一致的信息格式(錯誤代碼+錯誤信息)。
五、可預知的異常及不可預知的運行時異常最終會採用統一的信息格式(錯誤代碼+錯誤信息)來表示,最終也會隨
請求響應給客戶端。
項目使用RabbitMQ消息隊列。
RabbitMQ提供不少的工做模式,以下:
一、Work queues
二、Publish/Subscribe
三、Routing
四、Topics
五、Header
六、RPC
項目主要使用了Routing模式。
Routing模式即路由模式,使用方法是:
一、每一個消費者監聽本身的隊列,而且設置routingkey。
二、生產者將消息發給交換機,由交換機根據routingkey來轉發消息到指定的隊列。
有哪些應用場景?
1 、任務異步處理。
將不須要同步處理的而且耗時長的操做由消息隊列通知消息接收方進行異步處理。提升了應用程序的響應時間。
二、應用程序解耦合
MQ至關於一箇中介,生產方經過MQ與消費方交互,它將應用程序進行解耦合。
本項目採用 HLS 技術實現視頻點播。
一、使用FFmpeg對視頻進行編碼處理,生成m3u8文件及ts文件。
二、使用Nginx做爲媒體服務器。
三、客戶端使用video.js播放視頻。
例子:
在處理訂單時要用到定時任務,當時採用的是Spring Task來完成,因爲一個訂單服務會部署多個,多個訂單服務
同時去處理任務會形成任務被重複處理的狀況,如何解決任務的重複處理。
解決:
採用樂觀鎖解決,在任務表中設置一個version字段記錄版本號,取出任務記錄同時拿到任務的版本號,執行前對
任務進行鎖定,具體的作法是執行update根據當前版本號將版本號加1,update成功表示鎖定任務成功,便可開始
執行任務。
大概花了一個多月來作這個項目,感觸很深,瞭解了微服務在企業的開發流程,從需求分析丶環境搭建丶數據庫設計丶服務端開發丶前端丶測試丶部署等流程。雖然這個項目是2018年的,但不少技術都不算落後,用來作爲微服務項目經驗足以。作這個項目也遇到不少bug,明明按照視頻文檔一步一步的作,有時得不到本身想要的結果,而後就不停的調試,卸載重裝。一個問題可能作一下午也解決不了,有時會崩潰,這時候就作其餘事情分散注意力,好比洗個澡清醒一下再戰。不要灰心喪氣,急躁,當你解決了的就會有成就感,即便解決不了也盡力了。這就是咱們程序員的代碼精神吧。
後臺代碼:
https://github.com/Anmaking/xcEduService01.git
配套視頻課件:
連接:https://pan.baidu.com/s/1B4xXEYVgJh0A4j2IM2BAig 提取碼:48nn