先後端分離 - 爲何用Node.js搭建中間層

什麼是中間層

在翻看不少技術文章時,你們都提到「中間層」,在不少大型企業中,Node確實承擔了「中間層」的角色,那麼,Node爲何被普遍的應用在「中間層」呢? html

要回答這個問題,先來陳述下什麼是中間層。前端

一般咱們把Web領域分爲客戶端和服務端,也就是前端和後端,這裏的後端就包含了網關,靜態資源,接口,緩存,數據庫等。而中間層呢,就是在後端這裏再抽離一層出來,在業務上處理和客戶端銜接更緊密的部分,好比頁面渲染(SSR),數據聚合,接口轉發等等。web

以SSR來講,在服務端將頁面渲染好,能夠加快用戶的首屏加載速度,避免請求時白屏,還有利於網站作SEO,他的好處是比較好理解的。那麼對於數據的聚合,接口轉發來講,這樣作有什麼意義呢?數據庫

用Node的4點意義

業務驅動

Node有個突出的優點,他的開發者能夠是前端。 express

前端對於頁面所須要的數據有更好的理解,每一個頁面要用到哪些接口,每一個接口要用到哪些字段前端是最清楚的。再加上實際業務開發中,前端頁面需求常常會發生變化,須要修改字段或者數據結構,因此對接頁面的這部分接口由前端直接開發很是合適,能夠顯著的減小溝通成本。後端

架構須要

面向用戶的接口由Node中間層負責之後,真正的服務端能夠專一於提供基於領域模型的對內接口,作微服務。api

好比能夠基於Goods模型,提供全部商品相關的接口;基於Users模型,提供全部用戶相關接口。當一個接口須要商品+用戶信息時,由Node分別查詢組裝。從總體業務代碼維護角度來講,變得更容易,不會由於業務發展使得每一個接口都異常繁雜。瀏覽器

性能知足

若是僅僅是架構層面的需求,須要有一箇中間層來沉澱業務,那用Java,PHP也能夠作到,爲何說Node更適合作呢? 緩存

由於Node天生異步!性能優化

衆所周知,js是一門單線程語言,因此Node在實現的時候,須要藉助libuv來實現異步。

如圖所示,libuv爲Node提供了線程池,事件池,異步I/O等能力。正是由於其中網絡I/O的異步能力,可讓Node作接口聚合時,可以更高效的異步併發處理。

成本較低

Node使用js開發,只須要學習簡單的api,前端開發者就能夠無障礙使用,學習成本很低。

並且,Node具備活躍的社區和豐富的模塊池,擁有不少現成的功能實現。框架方面,也有成熟的koa,express等基本框架和egg等二次封裝框架,可根據需求選擇上手也比較方便。

 

案例:淘寶先後端分離實踐

爲何要先後端分離

  • 關注點分離
  • 職責分離
  • 對的人作對的事
  • 更好的共建模式
  • 快速的反應變化

階段一:後端MVC

VIEW層的兩種維護方式

1.前端寫Demo,後端套頁面

問題:後端須要寫HTML,且前端仍然須要確認後端寫的HTML。

2.前端寫View層,後端只管數據

問題:前端須要熟悉後端語言,且前端須要瞭解後端架構

問題1:前端代碼愈來愈複雜

  • 沒法統一協做模式,代碼充滿了約定
  • JS跟CSS,依賴於後段產出的HTML
  • 有的數據來自AJAX,有的數據印在DOM上
  • 有的業務邏輯在前端,有的在Model層,更多的是在View層

問題2:先後端依舊高度耦合

  • 前端依賴服務端開發環境
  • 在服務端View層高度耦合
  • 溝通成本高
  • 職責不清晰

問題3:沒法良好的支持跨終端

  • 業務邏輯散落在應用中
  • 渲染邏輯強依賴後端頁面
  • 只能用responsive design硬來

問題4:高度耦合的先後端分工

  • 溝通成本上升
  • 維護成本上升
  • 沒法正確且快速的響應變化
  • 代碼的腐爛只是早晚的問題

階段二:CLIENT-SIDE MV*

 

接口分離, 後端提供數據, 前端本身搞

  • MODEL層 - JAVASCRIPT OBJECT
  • VIEW層 - JAVASCRIPT TEMPLATE

業界滿坑滿谷的優秀方案:Backbone, EmberJS, KnockoutJS, AngularJS, React, etc.

先後端職責清晰了

後端 前端
  • 提供數據
  • 處理業務邏輯
  • Server-side MVC架構
  • 代碼跑在服務器上
  • 接收數據,返回數據
  • 處理渲染邏輯
  • Client-side MV* 架構
  • 代碼跑在瀏覽器上

 問題1:各層職責重疊,而且各玩各的

  • Client-side Model是Server-side Model 的加工
  • Client-side View跟Server-side是不一樣層次的東西
  • Client-side的Controller跟Sever-side的Controller各搞各的
  • Client-side的Route在Server-side可能沒有

問題2:性能問題

  • 渲染,取值都在客戶端進行,有性能的問題
  • 須要等待資源到齊才能進行,會有短暫白屏與閃動
  • 在移動設備低速網路的體驗奇差無比

問題3:重用問題

  • 模版沒法重用,形成維護上的麻煩與不一致
  • 邏輯沒法重用,前端的校驗後端仍須在作一次
  • 路由沒法重用,前端的路由在後端未必存在

問題4:跨終端問題

  • 業務太靠前,致使不一樣端重複實現
  • 邏輯太靠前,形成維護上的不易

問題5:SEO問題

  • 渲染都在客戶端,模版沒法重用,SEO實現麻煩

階段三:從新定義先後端

是依照工做職責來劃分的先後端,仍是依照硬體環境劃分的先後端?

傳統認知的先後端(按硬體環境劃分)

從新定義的先後端(按工做指責劃分)

在服務器(JAVA)與瀏覽器(JS)的中間架了一箇中間層(NODEJS)

WHY NODEJS

  • 前端熟悉的語言,學習成本低
  • 都是JS,能夠先後端複用
  • 體質適合:事件驅動非阻塞I/O
  • 適合IO密集型業務
  • 執行速度也不差

指責劃分

後端

前端

服務器 瀏覽器
JAVA NodeJS JS + HTML + CSS
  • 服務層
  • 提供數據接口
  • 維持數據穩定
  • 封裝業務邏輯
  • 跑在服務上的JS
  • 轉發數據,串接服務
  • 路由設計,控制邏輯
  • 渲染頁面,體驗優化
  • 更多的可能
  • 跑在瀏覽器上的JS
  • CSS、JS加載與運行
  • DOM操做
  • 任何的前端框架與工具
  • 共用模版、路由

職責清晰的架構 + 前端範圍的擴展 = 更多的可能

 

實際示例1:淘寶首頁優化 

需求

  • 靜態資料展現,方便運營管理
  • 更好的承載密集且龐大的流量

解決方案

  • 頁面緩存與定時刷新,返回緩存資料
  • NodeJS產出靜態頁面到CDN,定時刷新

實際示例2:淘寶詳情頁優化 

需求

  • 單日四億PV,頁面數據來自各個不一樣接口
  • 爲了避免影響體驗,先產生頁面框架後再發起多個異步請求取數據更新頁面。這些多出來的請求帶來的影響不小,尤爲在無線端

解決方案

在NodeJS端使用Bigpiper技術,合併請求,下降負擔,分批輸出,不影響體驗。

其餘優化:

頁面渲染優化

  • 先後端共享模版
  • 首屏服務器渲染
  • 次屏瀏覽器渲染
  • 局部刷新瀏覽器渲染

單頁面應用優化

  • 先後端共享路由與模版
  • 前端換頁,瀏覽器端渲染
  • 直接輸入網址,服務器渲染
  • SEO問題迎刃而解

可靠性優化
單元測試,頁面測試,迴歸測試,持續集成。

接口性能優化
拆分大接口爲獨立小接口,併發請求。串行 => 並行,大幅縮短請求時間。

部署優化
一臺NodeJS對多臺JAVA服務器,合理的分配服務器帶來最大的產出。

 

優化時秉承的思想:接口服務化   代碼模塊化   功能組件化

 

轉自:

https://2014.jsconfchina.com/slides/herman-taobaoweb/index.html#/

https://mp.weixin.qq.com/s/KzumZwo3ITX0TZvTIhq4vg

相關文章
相關標籤/搜索