前后端分離架構(gòu)概述

前后端分離已成為互聯(lián)網(wǎng)項目開發(fā)的業(yè)界標(biāo)準(zhǔn)使用方式。從經(jīng)典的JSP+Servlet+JavaBean的MVC時代空镜,到SSM(Spring + SpringMVC + Mybatis)和SSH(Spring + Struts + Hibernate)的Java 框架時代,再到前端框架(KnockoutJS、AngularJS、vueJS、ReactJS)為主的MV*時代潮针,然后是Nodejs引領(lǐng)的全棧時代,技術(shù)和架構(gòu)一直都在進(jìn)步倚喂。創(chuàng)新之路不會止步....
前端項目與后端項目是兩個項目每篷,放在兩個不同的服務(wù)器,需要獨立部署端圈,兩個不同的工程雳攘,兩個不同的代碼庫,不同的開發(fā)人員枫笛。前端只需要關(guān)注頁面的樣式與動態(tài)數(shù)據(jù)的解析及渲染吨灭,而后端專注于具體業(yè)務(wù)邏輯。

1刑巧、背景

前后端分離已成為互聯(lián)網(wǎng)項目開發(fā)的業(yè)界標(biāo)準(zhǔn)使用方式喧兄,通過nginx+tomcat的方式(也可以中間加一個nodejs)有效的進(jìn)行解耦,并且前后端分離會為以后的大型分布式架構(gòu)啊楚、彈性計算架構(gòu)吠冤、微服務(wù)架構(gòu)、多端化服務(wù)(多種客戶端恭理,例如:瀏覽器拯辙,車載終端,安卓颜价,IOS等等)打下堅實的基礎(chǔ)涯保。這個步驟是系統(tǒng)架構(gòu)從猿進(jìn)化成人的必經(jīng)之路。

核心思想是前端HTML頁面通過AJAX調(diào)用后端的RESTFUL API接口并使用JSON數(shù)據(jù)進(jìn)行交互周伦。

Web服務(wù)器:一般指像Nginx夕春,Apache這類的服務(wù)器,他們一般只能解析靜態(tài)資源专挪;

應(yīng)用服務(wù)器:一般指像Tomcat及志,Jetty,Resin這類的服務(wù)器可以解析動態(tài)資源也可以解析靜態(tài)資源寨腔,但解析靜態(tài)資源的能力沒有web服務(wù)器好速侈;

一般都是只有web服務(wù)器才能被外網(wǎng)訪問,應(yīng)用服務(wù)器只能內(nèi)網(wǎng)訪問迫卢。

以前的Java Web項目大多數(shù)都是Java程序員又當(dāng)?shù)之?dāng)媽倚搬,又搞前端,又搞后端靖避。隨著時代的發(fā)展潭枣,漸漸的許多大中小公司開始把前后端的界限分的越來越明確,前端工程師只管前端的事情幻捏,后端工程師只管后端的事情盆犁。正所謂術(shù)業(yè)有專攻,一個人如果什么都會篡九,那么他畢竟什么都不精谐岁。大中型公司需要專業(yè)人才,小公司需要全才榛臼,但是對于個人職業(yè)發(fā)展來說伊佃,前后端需要分離。

2沛善、未分離時代(各種耦合)

早期主要使用MVC框架航揉,Jsp+Servlet的結(jié)構(gòu)圖如下:


早期的MVC框架

大致就是所有的請求都被發(fā)送給作為控制器的Servlet,它接受請求金刁,并根據(jù)請求信息將它們分發(fā)給適當(dāng)?shù)腏SP來響應(yīng)帅涂。同時,Servlet還根據(jù)JSP的需求生成JavaBeans的實例并輸出給JSP環(huán)境尤蛮。JSP可以通過直接調(diào)用方法或使用UseBean的自定義標(biāo)簽得到JavaBeans中的數(shù)據(jù)媳友。需要說明的是,這個View還可以采用 Velocity产捞、Freemaker 等模板引擎醇锚。使用了這些模板引擎,可以使得開發(fā)過程中的人員分工更加明確坯临,還能提高開發(fā)效率焊唬。

那么,在這個時期看靠,開發(fā)方式有如下兩種:


方式一

方式二

方式二已經(jīng)逐漸淘汰求晶。主要原因有兩點:
1)前端在開發(fā)過程中嚴(yán)重依賴后端,在后端沒有完成的情況下衷笋,前端根本無法干活芳杏;
2)由于趨勢問題,會JSP辟宗,懂velocity爵赵,freemarker等模板引擎的前端越來越少;
因此泊脐,方式二逐漸不被采用空幻。然而,不得不說一點容客,方式一秕铛,其實很多小型傳統(tǒng)軟件公司至今還在使用约郁。

那么,方式一和方式二具有哪些共同的缺點呢?

  1. 前端無法單獨調(diào)試但两,開發(fā)效率低鬓梅;
  2. 前端不可避免會遇到后臺代碼,例如:
<body>
   <%
       request.setCharacterEncoding("utf-8")
       String name=request.getParameter("username");
       out.print(name);
   %>
</body>

這種方式耦合性太強谨湘。那么绽快,就算你用了freemarker等模板引擎,不能寫Java代碼紧阔。那前端也不可避免的要去重新學(xué)習(xí)該模板引擎的模板語法坊罢,無謂增加了前端的學(xué)習(xí)成本。正如我們后端開發(fā)不想寫前端一樣擅耽,你想想如果你的后臺代碼里嵌入前端代碼活孩,你是什么感受?因此乖仇,這種方式十分不妥诱鞠。

  1. JSP本身所導(dǎo)致的一些其他問題 比如,JSP第一次運行的時候比較緩慢这敬,因為里頭包含一個將JSP翻譯為Servlet的步驟航夺。再比如因為同步加載的原因,在JSP中有很多內(nèi)容的情況下崔涂,頁面響應(yīng)會很慢阳掐。

3、半分離時代

前后端半分離冷蚂,前端負(fù)責(zé)開發(fā)頁面缭保,通過接口(Ajax)獲取數(shù)據(jù),采用Dom操作對頁面進(jìn)行數(shù)據(jù)綁定蝙茶,最終是由前端把頁面渲染出來艺骂。這也就是Ajax與SPA應(yīng)用(單頁應(yīng)用)結(jié)合的方式,其結(jié)構(gòu)圖如下:


image.png

步驟如下:
(1)瀏覽器請求隆夯,CDN返回HTML頁面钳恕;
(2)HTML中的JS代碼以Ajax方式請求后臺的Restful接口;
(3)接口返回Json數(shù)據(jù)蹄衷,頁面解析Json數(shù)據(jù)忧额,通過Dom操作渲染頁面;
后端提供的都是以JSON為數(shù)據(jù)格式的API接口供Native端使用愧口,同樣提供給WEB的也是JSON格式的API接口睦番。

那么意味著WEB工作流程是:
1、打開web,加載基本資源托嚣,如CSS巩检,JS等;
2示启、發(fā)起一個Ajax請求再到服務(wù)端請求數(shù)據(jù)兢哭,同時展示loading;
3丑搔、得到j(luò)son格式的數(shù)據(jù)后再根據(jù)邏輯選擇模板渲染出DOM字符串;
4提揍、將DOM字符串插入頁面中web view渲染出DOM結(jié)構(gòu)啤月;
這些步驟都由用戶所使用的設(shè)備中逐步執(zhí)行,也就是說用戶的設(shè)備性能與APP的運行速度聯(lián)系的更緊換句話說就是如果用戶的設(shè)備很低端劳跃,那么APP打開頁面的速度會越慢谎仲。

為什么說是半分離的?因為不是所有頁面都是單頁面應(yīng)用刨仑,在多頁面應(yīng)用的情況下郑诺,前端因為沒有掌握controller層,前端需要跟后端討論杉武,我們這個頁面是要同步輸出呢辙诞,還是異步Json渲染呢?而且轻抱,即使在這一時期飞涂,通常也是一個工程師搞定前后端所有工作。因此祈搜,在這一階段较店,只能算半分離。

首先容燕,這種方式的優(yōu)點是很明顯的梁呈。前端不會嵌入任何后臺代碼,前端專注于HTML蘸秘、CSS官卡、JS的開發(fā),不依賴于后端醋虏。自己還能夠模擬Json數(shù)據(jù)來渲染頁面味抖。發(fā)現(xiàn)Bug,也能迅速定位出是誰的問題灰粮。

然而仔涩,在這種架構(gòu)下,還是存在明顯的弊端的粘舟。最明顯的有如下幾點:
1)JS存在大量冗余熔脂,在業(yè)務(wù)復(fù)雜的情況下佩研,頁面的渲染部分的代碼,非常復(fù)雜霞揉;
2)在Json返回的數(shù)據(jù)量比較大的情況下旬薯,渲染的十分緩慢,會出現(xiàn)頁面卡頓的情況适秩;
3)SEO( Search Engine Optimization绊序,即搜索引擎優(yōu)化)非常不方便,由于搜索引擎的爬蟲無法爬下JS異步渲染的數(shù)據(jù)秽荞,導(dǎo)致這樣的頁面骤公,SEO會存在一定的問題;
4)資源消耗嚴(yán)重扬跋,在業(yè)務(wù)復(fù)雜的情況下阶捆,一個頁面可能要發(fā)起多次HTTP請求才能將頁面渲染完畢∏仗可能有人不服洒试,覺得PC端建立多次HTTP請求也沒啥。那你考慮過移動端么朴上,知道移動端建立一次HTTP請求需要消耗多少資源么垒棋?

正是因為如上缺點,我們才亟需真正的前后端分離架構(gòu)痪宰。

4捕犬、分離時代

大家一致認(rèn)同的前后端分離的例子就是SPA(Single-page application),所有用到的展現(xiàn)數(shù)據(jù)都是后端通過異步接口(AJAX/JSONP)的方式提供的酵镜,前端只管展現(xiàn)碉碉。從某種意義上來說,SPA確實做到了前后端分離淮韭,但這種方式存在兩個問題:

  • WEB服務(wù)中垢粮,SPA類占的比例很少。很多場景下還有同步/同步+異步混合的模式靠粪,SPA不能作為一種通用的解決方案蜡吧;
  • 現(xiàn)階段的SPA開發(fā)模式,接口通常是按照展現(xiàn)邏輯來提供的占键,而且為了提高效率我們也需要后端幫我們處理一些展現(xiàn)邏輯昔善,這就意味著后端還是涉足了view層的工作,不是真正的前后端分離畔乙。

SPA式的前后端分離君仆,從物理層做區(qū)分(認(rèn)為只要是客戶端的就是前端,服務(wù)器端就是后端)這種分法已經(jīng)無法滿足前后端分離的需求,我們認(rèn)為從職責(zé)上劃分才能滿足目前的使用場景:

  • 前端負(fù)責(zé)view和controller層
  • 后端只負(fù)責(zé)model層返咱,業(yè)務(wù)處理與數(shù)據(jù)持久化等

controller層與view層對于目前的后端開發(fā)來說钥庇,只是很邊緣的一層,目前的java更適合做持久層咖摹、model層的業(yè)務(wù)评姨。
在前后端徹底分離這一時期,前端的范圍被擴展萤晴,controller層也被認(rèn)為屬于前端的一部分吐句。在這一時期:

  • 前端:負(fù)責(zé)View和Controller層。
  • 后端:只負(fù)責(zé)Model層店读,業(yè)務(wù)/數(shù)據(jù)處理等嗦枢。

可是服務(wù)端人員對前端HTML結(jié)構(gòu)不熟悉,前端也不懂后臺代碼呀两入,controller層如何實現(xiàn)呢净宵?這就是node.js的妙用了敲才,node.js適合運用在高并發(fā)裹纳、I/O密集、少量業(yè)務(wù)邏輯的場景紧武。最重要的一點是剃氧,前端不用再學(xué)一門其他的語言了,對前端來說阻星,上手度大大提高朋鞍。

可以就把Nodejs當(dāng)成跟前端交互的api⊥谆總得來說滥酥,NodeJs的作用在MVC中相當(dāng)于C(控制器)。Nodejs路由的實現(xiàn)邏輯是把前端靜態(tài)頁面代碼當(dāng)成字符串發(fā)送到客戶端(例如瀏覽器)畦幢,簡單理解可以理解為路由是提供給客戶端的一組api接口坎吻,只不過返回的數(shù)據(jù)是頁面代碼的字符串而已。

用NodeJs來作為橋梁架接服務(wù)器端API輸出的JSON宇葱。后端出于性能和別的原因瘦真,提供的接口所返回的數(shù)據(jù)格式也許不太適合前端直接使用喜德,前端所需的排序功能粱玲、篩選功能,以及到了視圖層的頁面展現(xiàn)挨决,也許都需要對接口所提供的數(shù)據(jù)進(jìn)行二次處理印颤。這些處理雖可以放在前端來進(jìn)行您机,但也許數(shù)據(jù)量一大便會浪費瀏覽器性能。因而現(xiàn)今,增加Node中間層便是一種良好的解決方案往产。

image.png

瀏覽器(webview)不再直接請求JSP的API被碗,而是:
1)瀏覽器請求服務(wù)器端的NodeJS;
2)NodeJS再發(fā)起HTTP去請求JSP仿村;
3)JSP依然原樣API輸出JSON給NodeJS锐朴;
4)NodeJS收到JSON后再渲染出HTML頁面;
5)NodeJS直接將HTML頁面flush到瀏覽器蔼囊;
這樣焚志,瀏覽器得到的就是普通的HTML頁面,而不用再發(fā)Ajax去請求服務(wù)器了畏鼓。

淘寶的前端團(tuán)隊提出的中途島(Midway Framework)的架構(gòu)如下圖所示:


image.png

增加node.js作為中間層酱酬,具體有哪些好處呢?

(1)適配性提升云矫;我們其實在開發(fā)過程中膳沽,經(jīng)常會給PC端、mobile让禀、app端各自研發(fā)一套前端挑社。其實對于這三端來說,大部分端業(yè)務(wù)邏輯是一樣的巡揍。唯一區(qū)別就是交互展現(xiàn)邏輯不同痛阻。如果controller層在后端手里,后端為了這些不同端頁面展示邏輯腮敌,自己維護(hù)這些controller阱当,模版無法重用,徒增和前端溝通端成本糜工。 如果增加了node.js層弊添,此時架構(gòu)圖如下:


image.png

在該結(jié)構(gòu)下,每種前端的界面展示邏輯由node層自己維護(hù)捌木。如果產(chǎn)品經(jīng)理中途想要改動界面什么的油坝,可以由前端自己專職維護(hù),后端無需操心钮莲。前后端各司其職免钻,后端專注自己的業(yè)務(wù)邏輯開發(fā),前端專注產(chǎn)品效果開發(fā)崔拥。

(2)響應(yīng)速度提升极舔;我們有時候,會遇到后端返回給前端的數(shù)據(jù)太簡單了链瓦,前端需要對這些數(shù)據(jù)進(jìn)行邏輯運算拆魏。那么在數(shù)據(jù)量比較小的時候盯桦,對其做運算分組等操作,并無影響渤刃。但是當(dāng)數(shù)據(jù)量大的時候拥峦,會有明顯的卡頓效果。這時候卖子,node中間層其實可以將很多這樣的代碼放入node層處理略号、也可以替后端分擔(dān)一些簡單的邏輯、又可以用模板引擎自己掌握前臺的輸出洋闽。這樣做靈活度玄柠、響應(yīng)度都大大提升。

舉個例子诫舅,即使做了頁面靜態(tài)化之后羽利,前端依然還是有不少需要實時從后端獲取的信息,這些信息都在不同的業(yè)務(wù)系統(tǒng)中刊懈,所以需要前端發(fā)送5这弧,6個異步請求來。有了NodeJs之后虚汛,前端可以在NodeJs中去代理這5個異步請求匾浪。還能很容易的做bigpipe,這塊的優(yōu)化能讓整個渲染效率提升很多泽疆。在PC上你覺得發(fā)5,6個異步請求也沒什么户矢,但是在無線端玲献,在客戶手機上建立一個http請求開銷很大殉疼。有了這個優(yōu)化,性能一下提升好幾倍捌年。

(3)性能得到提升瓢娜;大家應(yīng)該都知道單一職責(zé)原則。從該角度來看礼预,我們眠砾,請求一個頁面,可能要響應(yīng)很多個后端接口托酸,請求變多了褒颈,自然速度就變慢了,這種現(xiàn)象在mobile端更加嚴(yán)重励堡。采用node作為中間層谷丸,將頁面所需要的多個后端數(shù)據(jù),直接在內(nèi)網(wǎng)階段就拼裝好应结,再統(tǒng)一返回給前端刨疼,會得到更好的性能泉唁。

(4)異步與模板統(tǒng)一;淘寶首頁就是被幾十個HTML片段(每個片段一個文件)拼裝成揩慕,之前PHP同步include這幾十個片段亭畜,一定是串行的,Node可以異步迎卤,讀文件可以并行拴鸵,一旦這些片段中也包含業(yè)務(wù)邏輯,異步的優(yōu)勢就很明顯了蜗搔,真正做到哪個文件先渲染完就先輸出顯示宝踪。前端機的文件系統(tǒng)越復(fù)雜,頁面的組成片段越多碍扔,這種異步的提速效果就越明顯瘩燥。前后端模板統(tǒng)一在無線領(lǐng)域很有用,PC頁面和WIFI場景下的頁面適合前端渲染(后端數(shù)據(jù)Ajax到前端)不同,2G厉膀、3G弱網(wǎng)絡(luò)環(huán)境適合后端渲染(數(shù)據(jù)隨頁面吐給前端),所以同樣的模板二拐,在不同的條件下走不同的渲染渠道服鹅,模板只需一次開發(fā)。

增加NodeJS中間層后的前后端職責(zé)劃分:

image

5百新、總結(jié)

從經(jīng)典的JSP+Servlet+JavaBean的MVC時代企软,到SSM(Spring + SpringMVC + Mybatis)和SSH(Spring + Struts + Hibernate)的Java 框架時代,再到前端框架(KnockoutJS饭望、AngularJS仗哨、vueJS、ReactJS)為主的MV*時代铅辞,然后是Nodejs引領(lǐng)的全棧時代厌漂,技術(shù)和架構(gòu)一直都在進(jìn)步。雖然“基于NodeJS的全棧式開發(fā)”模式很讓人興奮斟珊,但是把基于Node的全棧開發(fā)變成一個穩(wěn)定苇倡,讓大家都能接受的東西還有很多路要走。創(chuàng)新之路不會止步囤踩,無論是前后端分離模式還是其他模式旨椒,都是為了更方便得解決需求,但它們都只是一個“中轉(zhuǎn)站”堵漱。前端項目與后端項目是兩個項目综慎,放在兩個不同的服務(wù)器,需要獨立部署怔锌,兩個不同的工程寥粹,兩個不同的代碼庫变过,不同的開發(fā)人員。前端只需要關(guān)注頁面的樣式與動態(tài)數(shù)據(jù)的解析及渲染涝涤,而后端專注于具體業(yè)務(wù)邏輯媚狰。


本文為轉(zhuǎn)載。原文版權(quán)聲明和鏈接如下:
版權(quán)聲明:本文為CSDN博主「fuzhongmin05」的原創(chuàng)文章阔拳,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議崭孤,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/fuzhongmin05/article/details/81591072

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末糊肠,一起剝皮案震驚了整個濱河市辨宠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌货裹,老刑警劉巖嗤形,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異弧圆,居然都是意外死亡赋兵,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門搔预,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霹期,“玉大人,你說我怎么就攤上這事拯田±欤” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵船庇,是天一觀的道長吭产。 經(jīng)常有香客問我,道長溢十,這世上最難降的妖魔是什么垮刹? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任达吞,我火速辦了婚禮张弛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘酪劫。我一直安慰自己吞鸭,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布覆糟。 她就那樣靜靜地躺著刻剥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滩字。 梳的紋絲不亂的頭發(fā)上造虏,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天御吞,我揣著相機與錄音,去河邊找鬼漓藕。 笑死陶珠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的享钞。 我是一名探鬼主播揍诽,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼栗竖!你這毒婦竟也來了暑脆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤狐肢,失蹤者是張志新(化名)和其女友劉穎添吗,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體份名,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡根资,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了同窘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玄帕。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖想邦,靈堂內(nèi)的尸體忽然破棺而出裤纹,到底是詐尸還是另有隱情,我是刑警寧澤丧没,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布鹰椒,位于F島的核電站,受9級特大地震影響呕童,放射性物質(zhì)發(fā)生泄漏漆际。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一夺饲、第九天 我趴在偏房一處隱蔽的房頂上張望奸汇。 院中可真熱鬧,春花似錦往声、人聲如沸擂找。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贯涎。三九已至,卻和暖如春慢洋,著一層夾襖步出監(jiān)牢的瞬間塘雳,已是汗流浹背陆盘。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留败明,地道東北人礁遣。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像肩刃,于是被迫代替她去往敵國和親祟霍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容