關于大型網站技術演進的思考(十四)–網站靜態化處理—前后端分離—上(6)

前文講到了CSI技術,這就說明網站靜態化技術的講述已經推進到了瀏覽器端了即真正到了web前端的范疇了,而時下web前端技術的前沿之一就是前后端 分離技術了,那么在這里網站靜態化技術和前后端分離技術產生了交集,所以今天我將討論下前后端分離技術,前后端分離技術討論完后,下一篇文章我將會以網站 靜態化技術的角度回過頭來重新審視下前后端分離技術,希望通過這種審視來加深我們對兩套技術的理解。

前后端分 離技術我個人認為是web前端被專業化以后的必由之路,而nodejs的出現是前后端分離技術的一個強興的催化劑,原因是nodejs的出現削平了前端技 術和服務端技術之間的鴻溝,使得前后端兩套不同技術體系進行真正意義的解耦提供了無限的可能性。但是如果我們把nodejs技術的使用認為就是實現了前后 端分離,這種理解又實在太膚淺了,下面我將講講我研究過的前后端分離技術方案,以及這些技術方案隱藏在背后思考,希望這些思考能給大家以一個新的思路來理 解前后端分離技術。

我們要深刻理解前后端分離技術有一個重要的前提,那就是要把前后端分離技術認為是傳統的web應用里的MVC設計模式的進一步演進。那么我們首先來看看MVC的定義,下面的內容摘錄于維基百科的解釋,具體如下:

MVC模式(Model-View-Controller)是軟件工程中的一種軟件架構模式,把軟件系統分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。

MVC模式最早由Trygve Reenskaug在1978年提出[1] ,是施樂帕羅奧多研究中心(Xerox PARC)在20世紀80年代為程序語言Smalltalk發明的一種軟件設計模式。MVC模式的目的是實現一種動態的程式設計,使后續對程序的修改和擴展簡化,并且使程序某一部分的重復利用成為可能。除此之外,此模式通過對復雜度的簡化,使程序結構更加直觀。軟件系統通過對自身基本部分分離的同時也賦予了各個基本部分應有的功能。專業人員可以通過自身的專長分組:

(控制器 Controller)- 負責轉發請求,對請求進行處理。

(視圖 View) – 界面設計人員進行圖形界面設計。

(模型 Model) – 程序員編寫程序應有的功能(實現算法等等)、數據庫專家進行數據管理和數據庫設計(可以實現具體的功能)。

各類用于 Web應用開發的語言里都有屬于自己的MVC框架,例如本人最熟悉的服務端語言java里就有大名鼎鼎的struts2,springMVC的MVC應用 框架,我早期從事java的web開發時候認為這些MVC框架都是非常的博大精深,用途廣泛,但是當我逐漸轉向了web前端技術開發以后又覺得這些框架的 很多功能顯得那么的多余和累贅,因此我曾寫過一篇文章專門討論過這些問題,該文章的名字叫做《為什么做java的web開發我們會使用struts2,springMVC和spring這樣的框架?》。

其實這篇 文章被寫的源頭就是在于我認為像struts2和springMVC這樣的框架做了太多瀏覽器本身就可以完成的工作,例如:頁面的渲染操作,因為服務端搶 了瀏覽器端的部分工作,這其實也就等于限制了web前端技術的深入運用,像很多前端的優化技術以及很多提升用戶體驗的技術就很難派上用場,之所以產生這些 問題,我認為傳統的MVC框架本質其實是一個服務端的MVC框架,雖然MVC設計模式里的V即View視圖層是想把界面開發工作專業化,讓界面設計人員能專心于界面開發,但是傳統的MVC框架下的View層的本質卻是一個不折不扣的服務端技術。

我們以java的web開發里jsp為例,JSP全名為Java Server Pages,中文名叫java服務器頁面,其根本是一個簡化的Servlet設計,它是java里動態網頁的技術標準, 這就說明jsp雖然看起來像html,其實它并不是真正的html,它需要被java的web容器進行解析轉化為瀏覽器可以解析的html頁面,然后通過 網絡傳輸到瀏覽器后,瀏覽器才能正確的展示這個jsp頁面,其他web開發語言里都有類似的動態網頁技術標準,但是不管什么語言的動態網頁技術標準,我們 使用它時候就是讓web前端技術被服務端技術所綁架,這也就是為什么每個招聘web前端工程師的崗位都要問你是否會java,php語言的源頭。但是隨著 互聯網的大發展,對web前端的要求是越來越專業化,web前端本身所包含的技術難度已經不亞于任何一個服務端語言開發難度,因此我們需要web前端更高 的專業化,而不希望web前端工程師被服務端技術束縛的更多而限制了自身能力的發展,這就導致前后端分離技術的出現。

不過前后 端分離技術的第一階段倒不是從改變view層即視圖層開始的,而是從連接客戶端和服務端的C層即控制層開始的,控制層既要作用于客戶端又要作用于服務端, 如果一個功能頁面是一個程序員從瀏覽器端一直寫到模型層,控制層也就不是什么問題了,但是如果當我們想按MVC的設計思想,讓界面開發人員專注于頁面開 發,服務端開發人員專注于服務端開發,那么這個時候控制層的歸屬問題就顯的非常重要了。在傳統的MVC框架里,因為M層和C層是使用同樣的語言體系,因此 我們很自然會把M層和C層的開發工作都交由服務端開發人員完成,這個決定無可厚非,但是傳統的MVC框架里V層和C層其本質也是同一個技術體系下的(例如 java的web開發里的jsp本質就是個servlet),因此V層和C層也是緊耦合的,因此界面開發人員開發頁面時候如何沒有C層支撐,那么這個頁面 其實是根本跑不起來的,如果前端開發人員這時候跑去寫寫C層即控制層的代碼,這就打破了原有的橫向分工,這個時候控制層的編碼工作就會變得混亂而難以控 制,看到這里有人一定會說既然控制層是屬于服務端的,那么前端技術人員就等等服務端的開發進度,再不行就自己寫個mock模擬下服務端的控制層,聽到這種 建議,我相信不管是前端的還是服務端的技術人員都會頭腦發麻,第一反應就是這不是自找麻煩啊,還不如一個人全部搞定算了。由此第一階段的前后端分離技術方 案出現了,這個方案需要解決的問題就是如何能讓web前端技術人員和web服務端技術人員協同起來工作,合理的分工,換句話說就是按web前端和web服 務端角度如何能橫向的分解web的開發工作。

前后端分離的第一階段需要解決問題的核心就是控制層的歸屬問題,從技術角度而言就是控制層到底是應該和視圖層解耦比較合理還是跟模型層解耦比較合理的問題。那么我們這里先回顧下MVC設計模式里對控制層的定義,維基百科里的定義是:

(控制器 Controller)- 負責轉發請求,對請求進行處理。

不過這個解釋我認為并不全面,以java的web開發里的控制層設計為例,我們發現控制層以溝通視圖層和模型層的角度而言,控制層其實主要完成三項具體的工作,它們分別是:

工作一:控制層起到一個路由的作用。客戶端請求到達控制層后,控制層根據請求內容將請求路由到服務端某個模型層進行處理,模型層將請求處理完畢后,會把響應結果返回給控制層,控制層在根據響應信息路由到特定的頁面。

工作二:控制層起到一個報文信息格式轉化的作用。這里以java的web開發為例,瀏覽器的數據都是以http報文形式發送給服務端,而控制層就是將http報文信息解析成java的對象,當然也可以是java的基本數據類型,然后控制層把解析好的信息傳遞給模型層進行處理。

工作三:傳統的MVC框架里,控制層其實深入參入到了頁面渲染的操作。在 java的web開發里的控制層不管如何被包裝,其本質就是一個servlet,而jsp頁面本質也是個serlvet,因此我們可以這么理解 jsp,jsp就是以頁面開發的方式寫java,而servlet就是以java的方式寫頁面,所以我們可以在servlet里以文件流的方式輸出頁面, 也可以讓servlet跳轉到jsp頁面。

由上面的 論述里我們發現,其實傳統MVC框架里控制層和模型層的聯系方式相對很簡單的,它們的聯系主要是路由和報文格式的轉化上,而控制層與視圖層的聯系除此之外 還多了一個頁面渲染,而頁面渲染本身應該是屬于瀏覽器的技術范疇,是瀏覽器技術不可分割的一部分,也是我上面內容里詬病傳統MVC框架問題所在,如果控制 層承擔了頁面渲染工作,那么控制層和視圖層的耦合度就變得非常高,要想將其解耦是十分困難,一般只有我們打破了現有MVC框架的技術體系才能完成,相比之 下,控制層與模型層的解耦就顯得容易多了。那么控制層與模型層如何解耦呢?具體如下:

首先我們 來解決下報文格式轉化的問題,這個技術方案很簡單就是借鑒http統一報文格式的特點,我們為控制層和模型層定義一套統一的報文格式,例如我們定義控制層 和模型層都以map的數據類型進行數據傳遞,這個map里有個專門的字段用來定義被路由到的模型接口信息,有個字段專門存儲需要傳遞的數據,具體的設計方 案可以根據實際的業務需要來設計。

接下來就 是路由的問題了,在解決報文格式轉化問題的論述里我講到要在統一報文格式里專門定義一個字段用來存儲該數據到底路由到哪個模型進行處理,不過這個字段并不 能完全解決路由問題,因此我們需要模型層對控制層提供一個統一的接口,任何控制層與模型層的溝通都通過這個統一接口來完成,只不過不同請求報文組裝的內容 不一樣而已,而這個接口還有個重要職責就是解析報文里的路由信息,讓請求能被正確的路由到對應的模型接口所處理。當然這個接口的返回值最好也是一個統一的 報文格式,這樣控制層解析模型層的返回數據也會便利的多了。

由上所述,我們發現第一階段的前后端分離工作控制層應該歸屬于web前端,這么做更加合理,也更加容易實現,其實之后進化版的前后端分離方案,控制層也都是屬于web前端,只不過形式不同而已,這個我在下一篇文章里繼續討論。

第一階段前后端分離方案解決的核心就是讓控制層和模型層解耦,這個方案進一步演化一下,我們可以把控制層和視圖層獨立成一個web應用,模型層也獨立成一個web應用,兩個web應用之間通過遠程調用方式進行溝通,這個方案我在以前文章里寫過,這篇文章的名字叫做《我設計的網站的分布式架構》。

這個進化 版的方案增加了系統開發的難度,因為我們需要增加網絡通信的編程以及遠程調用的實現,更麻煩的是我們還需要進行復雜的多線程編程,既然增加了開發的難度為 什么我還要這么做呢?首先我們通過應用分層,可以動態的調節web前端和web服務端的負載壓力,還可以在模型層之前提供一道安全屏障,不過被服務端綁架 的web前端在提升整個web應用負載能力這塊還是很有限的,其實這種做法的最大好處就是利于SOA框架的設計,也就是說這種架構我們可以為服務端的 SOA化提供有力的保障,因為控制層和模型層的解耦,可以讓模型層真正做到專注于業務,而不會再發生那種把業務邏輯寫到控制層的問題了從而降低代碼的健壯 性。

好了,今天就寫到這里,最好祝大家新年快樂,晚安了。

原創文章,作者:stanley,如若轉載,請注明出處:http://www.www58058.com/927

(0)
stanleystanley
上一篇 2015-03-11
下一篇 2015-03-11

相關推薦

  • M20 – 1- 第二周(2):硬鏈接與軟鏈接的區別

    在講硬鏈接與軟鏈接的區別之前,我們首先了解inode,了解inode讓我們更容易理解何為硬鏈接和軟鏈接。 inode概念        何為inode,inode就是索引節點,而inode表中存放著文件的元數據,何為元數據,元數據就是文件名稱、大小、時間戳、所有者、權限、inode等信息,而文件中的內容就是文件的數據,…

    Linux干貨 2016-08-02
  • Shell腳本編程

    Shell腳本編程 關于腳本的調試     bash -n /path/to/some_script                   &…

    Linux干貨 2016-08-15
  • N25-第一周 總結

    linux bassic The first week of blogging 概要 計算機與操作系統、linux發行版及他們之間聯系與區別、Linux的哲學思想、linux系統上命令使用格式及基礎命令介紹、linux命令幫助說明、FHS 一、計算機與操作系統 什么是計算機? 電子計算機(computer),亦稱電腦,是一種利用電子學原理,根據一系列指令對數…

    Linux干貨 2016-12-04
  • 任務計劃

    Linux 任務計劃、周期性任務執行 未來的某時間點執行一次任務 at batch :系統 自行選擇空閑時間去執行此處指定的任務 周期性運行某任務 cron [root@localhost ~]# rpm -q at (CentOS6中使用) at-3.1.10-48.el6.x86_64 [root@localhost ~]# rpm -ql at /et…

    Linux干貨 2017-05-13
  • 磁盤分區相關知識

    磁盤分區相關知識 使用磁盤分區的過程設備識別→設備分區→創建文件系統→標記文件系統→在/etc/fstab文件中創建條目→掛載新的文件系統 分區不是必須的,但是分區是必要的:優化I/O性能實現磁盤空間配額限制提高修復速度隔離系統和程序安裝多個OS采用不同文件系統 不重啟激活新添加的磁盤:echo “- – -” > …

    Linux干貨 2017-08-20
  • Nginx反向代理、負載均衡的實現

    概述:     上篇介紹了Nginx作為web服務器的一些常用配置的說明,但是在實際生產環境中,Nginx更多是作為前端的負載均衡器,反代前端用戶請求到后端真實的web服務器上,完成LNAMP的組合的方式存在。本篇就介紹一些Nginx作為http的反向代理和前端負載均衡調度器的一些常用配置,具體包括:  &n…

    Linux干貨 2016-11-01
欧美性久久久久