以 Flux 角度從頭考慮後端架構

筆記已通過時, 後面我開始了項目叫 Cumulo
http://cumulo.org/前端

這篇筆記寫的是我對於後端的架構的思考
最近對 React Flux 架構對數據層進行思考, 感受遇到了不少的問題
這些問題讓我以爲服務端在這方面沒有作好, 所以很懷疑後端架構
並且前端多種框架之間差異很是大, 然後端的彷佛沒有翻天覆地變化嘛數據庫

後端的結構

我作的是前端, 兩年前入門時看了很多輕型的框架, 主要是動態語言的
大體進行的工做是這樣一些:後端

  • 監聽請求, 對路由進行判斷瀏覽器

  • 解讀請求, 進行數據庫操做緩存

  • 渲染頁面或者 API, 返回給客戶端服務器

對於實時性有要求的頁面, 比較讓我關注的, 還要作另一下操做:網絡

  • 往相關客戶端推送數據更新數據結構

這個流程中間還有很多我不清楚的, 估計爲了程序方即是要作:架構

  • 對數據庫進行抽象, 好比 Node.js 中 Mongoose 將 MongoDB 封裝成 Model Collection併發

  • 使用緩存好比 Redis, 減小數據庫訪問, 減小頁面繪製, 提升性能

其餘恐怕還有不少, 我也不懂, 但這邊的討論總之限制在頁面渲染相關的

React Flux 的改變

React 的 Flux 方案對於前端好比 Backbone 來講, 有着很是大的變化:

  1. 瑣碎的 DOM 操做被限制, 儘可能不讓開發者手動進行控制

  2. 數據結構變簡單, 同時特別引入不可修改的數據, 減小出錯可能性

  3. 操做數據的方式從直接調用改爲了事件觸發, 避免外部操做數據

  4. 每次更新並不意味着對 View 進行一次更新, 而是設定時間段批量進行操做

  5. 嘗試用不可變數據, 方便查找數據的變化部分, 再提交給 View

  6. 棄用事件觸發的方式, 轉而使用 state 改變來描述界面變動

固然不能說每一點都很是有效, 可是 Flux 確實能讓前端開發簡單不少
對於交互多的實時的應用, 在 DOM 層面帶來的效率提高尤爲顯著
其次, 應用的內部邏輯相對過程式的寫法更清晰, 也更便於重用

在後端進行類比

上邊幾點不少是我特地提出來的, 每一點我嘗試在後端找一個 Node.js 上的對應:

  1. DOM 操做, 對於服務端來講, 就像是渲染 HTML 的部分
    考慮模版分離到了前端, 那麼僅僅對應界面變動部分的數據
    一般這樣的數據是服務端組裝好格式發送到客戶端的,, 相似手工寫 jQuery 語句
    對應地, 這個步驟有沒有可能交給框架去作呢?

  2. 數據結構上的封裝, Mongoose 的 Model 就像是 Backbone 的 Model
    數據庫部分其實有些像第一點的 DOM, 由於都是異步, 選擇器, 這些瑣碎的操做
    那麼數據庫是否能採用更簡單的抽象呢?

  3. 修改數據的請求, 對於服務端來講都是 HTTP 的事件, 自己就很像

  4. 合併操做的問題, 由於 push 的網絡傳輸自己是緩慢的, 也存在問題
    同時後端的 cache 策略和 React 用 DOM Diff 避免性能開銷也很是像
    那麼合併將要推送的數據是否能帶來一些改善呢?

  5. 數據改變部分, 當一次請求帶來多個數據改變, 往客戶端推送增量相對繁瑣
    只是換個角度考慮一下, 直接在服務端模擬 diff 的方案有沒有可能?

  6. 事件部分, Express 的路由和 Backbone 的路由挺像, 監聽事件調用操做
    對應在 React 當中, 邏輯部分的事件全給抽象掉了(DOM 的事件在所不免)
    而在 Node 當中 IO 幾乎都抽象成了事件回調, 可想事件將是頻繁出現的
    那麼有沒有可能將事件用狀態在內部邏輯當中進行一些替換?

Flux 的方案若是用在後端

關於上邊的問題目前沒了解到好的答案, 不過倒能夠設想下若是用 Flux 將如何?
界面上的一個操做, 到其餘客戶端更新界面, 整個流程:

  1. 界面操做事件被監聽, 表單被經過 WebSocket 往服務器提交

  2. 服務器接收到數據, 在內部對數據進行更改

  3. 經歷一個事件循環, 服務器開始計算每一個客戶端所需的所有數據,
    而且根據服務端保存的客戶端的舊副本作 diff 查找出更新部分

  4. diff 被髮送到全部關聯的客戶端, 客戶端更新副本, 或者說是同步

  5. 數據更新觸發 React 的 Virtual DOM 更新, 最終界面被更新

這樣完整的一個流程變得跟簡單的模版渲染頁面同樣清晰
而單次修改後組裝數據的工做, 也不須要人工進行完成
單純這樣想是很好了, 同時也存在着明顯的性能問題:

  1. 對數據庫裏的大量數據不可能作 diff, 最少也要根據時間排除舊數據
    或者其餘方案, 總之如今沒有個現成的方案這樣跑下來同時還能保證性能

  2. 客戶端的數據備份徹底跟着服務端改變, 意味着客戶端不處理數據的邏輯了
    所以服務端就須要維護全部客戶端的數據部分
    一個事件循環後要爲全部的客戶端計算一遍數據, 併發量不小

  3. 服務端須要知道客戶端完整的狀態, 這已經不是 server 的概念了
    而是繼續回到服務端 M 和 C, 服務端 V 這樣的形態
    不一樣的是原先寫在 url 裏的狀態, 如今須要在服務器保存和維護
    同時必須有 WebSocket 將兩端緊密聯繫在一塊兒

實時應用

前邊寫了那麼多, 使用的範圍估計也能看明白了, 這個是實時的應用
目前的方案是前端 MVC, 而前端 MVC 某種程度上是個奇葩的技術方案
由於在服務端和客戶端分別有 Model 和 Controller, 就存在冗餘代碼
冗餘代碼還會致使分工不明確, 甚至修改邏輯時易於出現遺漏
此前前端 MVC 已經面臨了模塊先後端共用和分工的問題, 如今 M 和 V 也來了

對於實時應用呢, 咱們知道 Meteor 和 Derby 已經探索好久了
好比 Meteor 能在客戶端直接操做 MongoDB 觸發其餘的客戶端更新
好比 Derby 的同步引擎 racer 能同步本地的數據操做到服務器
相對 React 來講, 區別在於這個邏輯是寫在瀏覽器端的, 而不是服務端
我沒有深刻研究過兩個框架, 具體架構如何只能等別人寫文章討論了

總之這裏有一個問題, 就意味着有可能被人解決, 意味着 Web 開發可能更簡單React 處理單頁面已經不錯了, 可是多人蔘與的應用有個服務端是必不可少的Flux 沒怎麼講關於服務端的邏輯.. 不過, 他們做爲 MVC 應該有一些通用的思想最後就期待問題能早點有個可行的方案填上吧

相關文章
相關標籤/搜索