前后端分離實踐的架構設計分析
- 發布時間:2021-01-20
摘要
在當前互聯網軟件開發模式中,一部分公司在軟件開發方面采用傳統的開發模式,即:系統功能實現主要以后臺為主,前端人員只負責寫HTML或者JavaScript代碼。在該方式下的程序前后端高度耦合,系統維護困難。文章通過對傳統的軟件開發方式進行分析,引入當前流行的前后端分離軟件設計方式,進行深入闡述分析。
關鍵詞:軟件結構;前后端分離
1、概述
前后端分離已成為互聯網項目開發的業界標準使用方式,通過nginx+tomcat的方式(也可以中間加一個nodejs)有效的進行解耦,并且前后端分離會為以后的大型分布式架構、彈性計算架構、微服務架構、多端化服務(多種客戶端,例如:瀏覽器,車載終端,安卓,IOS等等)打下堅實的基礎。
核心思想是前端html頁面通過ajax調用后端的restuful api接口并使用json數據進行交互。
在互聯網架構中,名詞解釋:
Web服務器:一般指像nginx,apache這類的服務器,他們一般只能解析靜態資源。
應用服務器:一般指像tomcat,jetty,resin這類的服務器可以解析動態資源也可以解析靜態資源,但解析靜態資源的能力沒有web服務器好。
一般都是只有web服務器才能被外網訪問,應用服務器只能內網訪問。
2、發展歷程
2.1未分離時代
早期主要使用MVC框架,Jsp+Servlet的結構圖如下:
大致就是所有的請求都被發送給作為控制器的Servlet,它接受請求,并根據請求信息將它們分發給適當的JSP來響應。同時,Servlet還根據JSP的需求生成JavaBeans的實例并輸出給JSP環境。JSP可以通過直接調用方法或使用UseBean的自定義標簽得到JavaBeans中的數據。 需要說明的是,這個View還可以采用Velocity、Freemaker等模板引擎。使用了這些模板引擎,可以使得開發過程中的人員分工更加明確,還能提高開發效率。
2.2半分離時代
幾曾何時,我們的JavaWeb項目都是使用了若干后臺框架,springmvc/struts+spring+jdbc/hibernate/mybatis等等。
大多數項目在java后端都是分了三層,控制層,業務層,持久層??刂茖迂撠熃邮諈?,調用相關業務層,封裝數據,以及路由渲染到jsp頁面。然后jsp頁面上使用各種標簽或者手寫java表達式將后臺的數據展現出來。
前后端半分離,前端負責開發頁面,通過接口(Ajax)獲取數據,采用Dom操作對頁面進行數據綁定,最終是由前端把頁面渲染出來。這也就是Ajax與單頁應用結合的方式,其結構圖如下:
2.3分離時代
隨著互聯網技術的高速發展,目前Web項目所需要應付的場景和以往有著很大的不同,以往的時候我們將代碼、數據庫放在同一個服務器中,所有的壓力都由一個服務器承擔。但目前各個網站訪問量都有了很大的上升。如果還是將所有的應用放在一個服務器中,很容易使得服務器崩潰,為解決這類問題,現在許多系統都是用集群或者分布式模式,將一個項目部署到多個服務器或者分為多個子項目分別部署。當用戶發送請求時,走完一個請求的全部流程可能需要經過多個服務器,還存在著請求跨域的問題,如果項目前后端耦合度較高,那么必然使得系統復雜性上升。為解決這一情況,前后端分離已經變成了一種必然的趨勢。前后端分離是指將前端和后端從之前的相互融合中分離開來,兩者不再共用一個Server,前端作為一個獨立Server存在。這種情況下使得一部分業務邏輯轉移到前端,后臺通過API將數據交給前端后對前端就已經是無感知狀態,后端不再接觸任何的HTML或者模板頁面,前端獲得數據后進行業務邏輯的處理。目前市面上流行的前端框架分別為:VueJS,React,Angular,使用這些框架都能很好地實現前后端分離,其中VueJS和Angular都使用了MVVM的開發模式實現業務邏輯,MVVM是對MVC的一個改進,將其中的View的狀態和行為進行抽象化,將頁面和業務分開。視圖獨立于模型而存在,單獨對視圖或模型修改不會影響對方,同時可以將一些視圖邏輯放到一個ViewModel中,實現邏輯的重用。結構圖如下:
2.3.1、對于后端java工程師
把精力放在java基礎,設計模式,jvm原理,spring+springmvc原理及源碼,linux,mysql事務隔離與鎖機制,mongodb,http/tcp,多線程,分布式架構,彈性計算架構,微服務架構,java性能優化,以及相關的項目管理等等。
后端追求的是:三高(高并發,高可用,高性能),安全,存儲,業務等等。
2.3.2、對于前端工程師
把精力放在html5,css3,jquery,angularjs,bootstrap,reactjs,vuejs,webpack,less/sass,gulp,nodejs,Google V8引擎,javascript多線程,模塊化,面向切面編程,設計模式,瀏覽器兼容性,性能優化等等。
前端追求的是:頁面表現,速度流暢,兼容性,用戶體驗等等。
通過將team分成前后端team,讓兩邊的工程師更加專注各自的領域,獨立治理,然后構建出一個全棧式的精益求精的team。
3、JSP的痛點
以前的javaWeb項目大多數使用jsp作為頁面層展示數據給用戶,因為流量不高,因此也沒有那么苛刻的性能要求,但現在是大數據時代,對于互聯網項目的性能要求是越來越高,因此原始的前后端耦合在一起的架構模式已經逐漸不能滿足我們,因此我們需要尋找一種解耦的方式,來大幅度提升我們的負載能力。
1、動態資源和靜態資源全部耦合在一起,服務器壓力大,因為服務器會收到各種http請求,例如css的http請求,js的,圖片的等等。一旦服務器出現狀況,前后臺一起玩完,用戶體驗極差。
2、UI出好設計圖后,前端工程師只負責將設計圖切成html,需要由java工程師來將html套成jsp頁面,出錯率較高(因為頁面中經常會出現大量的js代碼),修改問題時需要雙方協同開發,效率低下。
3、jsp必須要在支持java的web服務器里運行(例如tomcat,jetty,resin等),無法使用nginx等(nginx單實例http并發高達5w,這個優勢要用上),性能提不上來。
4、第一次請求jsp,必須要在web服務器中編譯成servlet,第一次運行會較慢。
5、每次請求jsp都是訪問servlet再用輸出流輸出的html頁面,效率沒有直接使用html高。
6、jsp內有較多標簽和表達式,前端工程師在修改頁面時會捉襟見肘,遇到很多痛點。
7、如果jsp中的內容很多,頁面響應會很慢,因為是同步加載。
8、需要前端工程師使用java的ide(例如eclipse、idea),以及需要配置各種后端的開發環境。
4、開發模式
4.1以前老的方式是
1、產品經歷/領導/客戶提出需求。
2、UI做出設計圖。
3、前端工程師做html頁面。
4、后端工程師將html頁面套成jsp頁面(前后端強依賴,后端必須要等前端的html做好才能套jsp。如果html發生變更,就更痛了,開發效率低)。
5、集成出現問題。
6、前端返工。
7、后端返工。
8、二次集成。
9、集成成功。
10、交付。
4.2新的方式是
1、產品經歷/領導/客戶提出需求。
2、UI做出設計圖。
3、前后端約定接口&數據&參數。
4、前后端并行開發(無強依賴,可前后端并行開發,如果需求變求變更,只要接口&參數不變,就不用兩邊都修改代碼,開發效率高)。
5、前后端集成。
6、前端頁面調整。
7、集成成功。
8、交付。
5、請求方式
5.1以前老的方式是
1、客戶端請求。
2、服務端的servlet或controller接收請求(后端控制路由與渲染頁面,整個項目開發的權重大部分在后端)。
3、調用service,dao代碼完成業務邏輯。
4、返回jsp。
5、jsp展現一些動態的代碼。
5.2新的方式是
1、瀏覽器發送請求。
2、直接到達html頁面(前端控制路由與渲染頁面,整個項目開發的權重前移)。
3、html頁面負責調用服務端接口產生數據(通過ajax等等,后臺返回json格式數據,json數據格式因為簡潔高效而取代xml)。
4、填充html,展現動態效果,在頁面上進行解析并操作DOM。
總結一下新的方式的請求步驟:
大量并發瀏覽器請求--->web服務器集群(nginx)--->應用服務器集群(tomcat)--->文件/數據庫/緩存/消息隊列服務器集群。
6、前后分離的優勢
1、可以實現真正的前后端解耦,前端服務器使用nginx。前端/WEB服務器放的是css,js,圖片等等一系列靜態資源(甚至你還可以css,js,圖片等資源放到特定的文件服務器,例如阿里云的oss,并使用cdn加速),前端服務器負責控制頁面引用&跳轉&路由,前端頁面異步調用后端的接口,后端/應用服務器使用tomcat(把tomcat想象成一個數據提供者),加快整體響應速度。
2、發現bug,可以快速定位是誰的問題,不會出現互相踢皮球的現象。頁面邏輯,跳轉錯誤,瀏覽器兼容性問題,腳本錯誤,頁面樣式等問題,全部由前端工程師來負責。接口數據出錯,數據沒有提交成功,應答超時等問題,全部由后端工程師來解決。雙方互不干擾。
3、在大并發情況下,我可以同時水平擴展前后端服務器,比如淘寶的一個首頁就需要2000+臺前端服務器做集群來抗住日均多少億+的日均pv。
4、減少后端服務器的并發/負載壓力。除了接口以外的其他所有http請求全部轉移到前端nginx上,接口的請求調用tomcat,參考nginx反向代理tomcat。且除了第一次頁面請求外,瀏覽器會大量調用本地緩存。
5、即使后端服務暫時超時或者宕機了,前端頁面也會正常訪問,只不過數據刷不出來而已。
6、也許你也需要有微信相關的輕應用,那樣你的接口完全可以共用,如果也有app相關的服務,那么只要通過一些代碼重構,也可以大量復用接口,提升效率。(多端應用)
7、頁面顯示的東西再多也不怕,因為是異步加載。
8、nginx支持頁面熱部署,不用重啟服務器,前端升級更無縫。
9、增加代碼的維護性&易讀性(前后端耦在一起的代碼讀起來相當費勁)。
10、提升開發效率,因為可以前后端并行開發,而不是像以前的強依賴。
11、在nginx中部署證書,外網使用https訪問,并且只開放443和80端口,其他端口一律關閉(防止黑客端口掃描),內網使用http,性能和安全都有保障。
12、前端大量的組件代碼得以復用,組件化,提升開發效率,抽出來!
7、注意事項
1、在開需求會議的時候,前后端工程師必須全部參加,并且需要制定好接口文檔,后端工程師要寫好測試用例(2個維度),不要讓前端工程師充當你的專職測試,推薦使用chrome的插件postman或soapui或jmeter,service層的測試用例拿junit寫。
2、上述的接口并不是java里的interface,調用接口就是調用你controler里的方法。
3、加重了前端團隊的工作量,減輕了后端團隊的工作量,提高了性能和可擴展性。
4、我們需要一些前端的框架來解決類似于頁面嵌套,分頁,頁面跳轉控制等功能。(上面提到的那些前端框架)。
5、如果頁面上有一些權限等等相關的校驗,那么這些相關的數據也可以通過ajax從接口里拿。
6、對于既可以前端做也可以后端做的邏輯,建議放到前端,因為你的邏輯需要計算資源進行計算,如果放到后端去run邏輯,則會消耗帶寬&內存&cpu等等計算資源,服務端的計算資源是有限的,而如果放到前端,使用的是客戶端的計算資源,這樣你的服務端負載就會下降(高并發場景)。類似于數據校驗這種,前后端都需要做!
7、前端需要有機制應對后端請求超時以及后端服務宕機的情況,友好的展示給用戶。
8、總結
本文介紹了軟件開發中前后端模式的基本歷程。軟件開發中前后端進行分離后由后端提供數據然后前端來進行渲染使得項目分工明確,開發過程中前后端可以各自測試已經完成的功能,最后將前后端進行對接,有效地提升開發效率。前后端分離并非僅僅只是一種開發模式,而是一種架構模式(前后端分離架構)。千萬不要以為把前端和后端分開就是前后端分離了,需要區分前后端項目。前端項目與后端項目是兩個項目,放在兩個不同的服務器,需要獨立部署,兩個不同的工程,兩個不同的代碼庫,不同的開發人員。前后端工程師需要約定交互接口,實現并行開發,開發結束后需要進行獨立部署,前端通過ajax來調用http請求調用后端的restful api。前端只需要關注頁面的樣式與動態數據的解析&渲染,而后端專注于具體業務邏輯。