為什麼JavaWeb放棄jsp,去做前後端分離

糖寶發表於2019-01-19

前後端分離已成為網際網路專案開發的業界標準使用方式,通過nginx+tomcat的方式(也可以中間加一個nodejs)有效的進行解耦,並且前後端分離會為以後的大型分散式架構、彈性計算架構、微服務架構、多端化服務(多種客戶端,例如:瀏覽器,車載終端,安卓,IOS等等)打下堅實的基礎。這個步驟是系統架構從猿進化成人的必經之路。

核心思想:前端html頁面通過ajax呼叫後端的restuful api介面並使用json資料進行互動。

在網際網路架構中,

web伺服器:一般指像nginx,apache這類的伺服器,他們一般只能解析靜態資源。

應用伺服器:一般指像tomcat,jetty,resin這類的伺服器可以解析動態資源也可以解析靜態資源,但解析靜態資源的能力沒有web伺服器好。

一般都是隻有web伺服器才能被外網訪問,應用伺服器只能內網訪問。

以前的JavaWeb專案大多數都是java程式設計師又當爹又當媽,又搞前端(ajax/jquery/js/html/css等等),又搞後端(java/mysql/oracle等等)。

隨著時代的發展,漸漸的許多大中小公司開始把前後端的界限分的越來越明確,前端工程師只管前端的事情,後端工程師只管後端的事情。正所謂術業有專攻。

對於後端java工程師:

把精力放在java基礎,設計模式,jvm原理,spring+springmvc原理及原始碼,linux,mysql事務隔離與鎖機制,mongodb,http/tcp,多執行緒,分散式架構(dubbo,dubbox,spring cloud),彈性計算架構,微服務架構(springboot+zookeeper+docker+jenkins),java效能優化,以及相關的專案管理等等。

後端追求的是:三高(高併發,高可用,高效能),安全,儲存,業務等等。

對於前端工程師:

把精力放在html5,css3,jquery,angularjs,bootstrap,reactjs,vuejs,webpack,less/sass,gulp,nodejs,Google V8引擎,javascript多執行緒,模組化,面向切面程式設計,設計模式,瀏覽器相容性,效能優化等等。

前端追求的是:頁面表現,速度流暢,相容性,使用者體驗等等。

通常我們的JavaWeb專案都是使用了若干後臺框架,springmvc/struts + spring + spring jdbc/hibernate/mybatis 等等。大多數專案在java後端都是分了三層,控制層(controller/action),業務層(service/manage),持久層(dao)。控制層負責接收引數,呼叫相關業務層,封裝資料,以及路由&渲染到jsp頁面。然後jsp頁面上使用各種標籤(jstl/el/struts標籤等)或者手寫java表示式(<%=%>)將後臺的資料展現出來,玩的是MVC那套思路。緊接著系統釋出,你需要用maven或者eclipse等工具把你的程式碼打成一個war包,然後把這個war包釋出到你的生產環境下的web容器(tomcat/jboss/weblogic/websphere/jetty/resin)裡,對吧?釋出完了之後,你要啟動你的web容器,開始提供服務,這時候你通過配置域名,dns等等相關,你的網站就可以訪問了。這樣一來,你的前後端程式碼全都在那個war包裡了,包括你的js,css,圖片,各種第三方的庫。

在瀏覽器中輸入你的網站域名(www.xxx.com),之後發生了什麼?瀏覽器通過域名,再通過dns伺服器找到你的伺服器外網ip,將http請求傳送到你的伺服器,在tcp3次握手之後(http下面是tcp/ip),通過tcp協議開始傳輸資料,你的伺服器得到請求後,開始提供服務,接收引數,之後返回你的應答給瀏覽器,瀏覽器再通過content-type來解析你返回的內容,呈現給使用者。

我們先假設你的首頁中有100張圖片,此時,使用者的看似一次http請求,其實並不是一次,使用者在第一次訪問的時候,瀏覽器中不會有快取,你的100張圖片,瀏覽器要連著請求100次http請求(有人會跟我說http長連短連的問題,不在這裡討論),你的伺服器接收這些請求,都需要耗費記憶體去建立socket來玩tcp傳輸(消耗你伺服器上的計算資源)。這樣的話,你的伺服器的壓力會非常大,因為頁面中的所有請求都是隻請求到你這臺伺服器上,如果1個人還好,如果10000個人併發訪問呢(先不聊伺服器叢集,這裡就說是單例項伺服器),那你的伺服器能扛住多少個tcp連線?你的頻寬有多大?你的伺服器的記憶體有多大?你的硬碟是高效能的嗎?你能抗住多少IO?你給web伺服器分的記憶體有多大?會不會當機?

這就是為什麼,越是大中型的web應用,他們越是要解耦。

理論上你可以把你的資料庫+應用服務+訊息佇列+快取+使用者上傳的檔案+日誌+等等都扔在一臺伺服器上,你也不用玩什麼服務治理,也不用做什麼效能監控,什麼報警機制等等。但是這樣把雞蛋都放在一個籃子裡,隱患非常大。如果因為一個子應用的記憶體不穩定導致整個伺服器記憶體溢位而hung住,那你的整個網站就掛掉了。

JSP的痛點:

以前的javaWeb專案大多數使用jsp作為頁面層展示資料給使用者,因為流量不高,因此也沒有那麼苛刻的效能要求,但現在是大資料時代,對於網際網路專案的效能要求是越來越高。

1.動態資源和靜態資源全部耦合在一起,伺服器壓力大,因為伺服器會收到各種http請求,例如css的http請求,js的,圖片的等等。一旦伺服器出現狀況,前後臺一起玩完,使用者體驗極差。

2.UI出好設計圖後,前端工程師只負責將設計圖切成html,需要由java工程師來將html套成jsp頁面,出錯率較高,修改問題時需要雙方協同開發,效率低下。

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),以及需要配置各種後端的開發環境,你們有考慮過前端工程師的感受嗎。

基於上述的一些痛點,我們應該把整個專案實現前後端真正的解耦!

前後分離的優勢:

1.可以實現真正的前後端解耦,前端伺服器使用nginx。

前端/WEB伺服器放的是css,js,圖片等等一系列靜態資源(甚至你還可以css,js,圖片等資源放到特定的檔案伺服器,例如阿里雲的oss,並使用cdn加速),前端伺服器負責控制頁面引用&跳轉&路由,前端頁面非同步呼叫後端的介面,後端/應用伺服器使用tomcat(把tomcat想象成一個資料提供者),加快整體響應速度。

(這裡需要使用一些前端工程化的框架比如nodejs,react,router,react,redux,webpack)

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.前端大量的元件程式碼得以複用,元件化,提升開發效率,抽出來!
分享個學習Java交流裙678241563裡面有軟體視訊資料

總結一下新的方式的請求步驟:

大量併發瀏覽器請求—>web伺服器叢集(nginx)—>應用伺服器叢集(tomcat)—>檔案/資料庫/快取/訊息佇列伺服器叢集

同時又可以玩分模組,還可以按業務拆成一個個的小叢集,為後面的架構升級做準備。

相關文章