為什麼互聯網公司開始用node.js做web服務的中間件?有什麼好處嗎?


本回答無意於辯證某種選型的優劣,只是闡述了這個現象背後的思考和選擇。

微服務架構下的企業開發困境

近幾年來,在企業開發中越來越推崇微服務架構,而它在不經意間卻導致前端同學和後端同學之間關於 API 介面顆粒度的爭吵,越來越多見:

  • 「你自己請求 2 個介面再組裝不就行了?」 - 後端同學追求服務下沉和解耦。
  • 「少一次 HTTP 啊,加一個介面有那麼難么?」 - 前端同學離用戶最近,需要考慮用戶體驗靈活性。

歸結為一個問題:『服務端設計的介面究竟是面向 UI 還是只是通用服務?』

BFF 的提出

2015 年,Sam Newman 對此提出了 Pattern: Backends For Frontends,簡稱 BFF,國內也俗稱為粘合層。

乍一看,似乎這一層一直都存在,只不過是由後端同學維護而已。

但我們知道,前端貼近用戶側,需求的變化太快了,後端同學來維護會很累。

在 BFF 理念中,最重要的一點是:服務自治,誰使用誰開發,即它應該由前端同學去維護。

  • 服務自治減少了溝通成本,帶來了靈活和高效。
  • 自己吃自己的狗糧。
  • BFF 並不限制具體技術,團隊根據自己的技術棧來選型: Java/Node/PHP/Python/Ruby...
  • 基於 GraphQL 技術的通用中間層網關,也是剛剛出現一種很不錯的方案。
  • 在大部分前端團隊中,都會傾向於選擇生態更優,語法更熟悉的 Node.js 。

這塊 @湯堯 在 D2 2016 上也分享了 『螞蟻財富的 BFF 實踐』。

在 BFF 之上,螞蟻又進一步實踐了 『Developer Experience First - TWA 的理念與實踐』,這塊 @死馬 在 螞蟻體驗科技大會 (2018.01.06) 上會有更深入的分享。


所以,回到題主的問題:

為什麼互聯網公司開始用node.js做web服務的中間件?有什麼好處嗎?

無它,就是需要這樣的一個中間層,但後端同學不太想管了(也管不過來),所以大部分前端同學選擇了一個更順手的 Node.js ,僅此而已。

太好了,我馬上要用 Node.js

不,你需要根據你的業務場景,還有團隊的技術架構,來具體情況具體分析。切記, BFF 不限制具體技術選型。


當然也因此帶來了一些其他問題,如最近的月經貼『 node相比傳統服務端技術棧差在哪裡?』

比較認同裡面一些答主提到的,Node.js 還是太年輕了,我們還在路上,有很多問題等著去翻越。

所幸的是,阿里自從 2011 年開始就使用 Node.js,並一路前行:

  • @朴靈 的 AliNode 專治內存和性能等疑難雜症
  • @蘇千 的 cnpm 提速 GFW 之痛
  • 阿里在 Web 框架這個領域的實踐 -『如何評價阿里開源的企業級 Node.js 框架 EggJS?』
  • 目前我們有 500+ Node 開發者,數千 Node 應用,可以看下 @張秋怡 分享的 『Node.js at Alibaba』。
  • 在 IoT,React 同構等方面的探索 - D2前端技術論壇 2017

說這麼多,還不如直接進來『眼見為實』,歡迎私信勾搭。


好處如下:

  • 前端到後端的適配層是非常 dirty 的一層代碼,經常要加入各種特殊處理,使用腳本開發成本低。並且這一層由於基本上就是做各種對象到對象的翻譯,不太會出現難以排查的錯誤,就算有這樣的錯誤,強類型語言對避免這種錯誤也沒什麼幫助。同時,這一層屬於典型的無狀態 IO 密集型模塊,非常適合吞吐能力巨大的 node.js 開發,用 java 開發也不會帶來什麼額外的性能優勢。
  • 前端對這一層的變動需求,要比後端多得多,本著「誰用誰維護,誰爽誰負責」的原則,這一層應該由前端維護,使用 node.js 編寫這一層對前端來說更友好。


首先,互聯網用 Node.js 做中間層已經很多年了,所採用的架構也各式各樣。有簡單 Proxy 的,有 BFF 的,有 FFB 的,也有純 Render 的等等等,花樣特別多。

其實背後有個時代背景:前端發揮著越來越重要的作用

特別是 Node 8 之後的性能飆升,TypeScript 也讓項目更具維護性和擴展性,高水平選手越來越多。那緊接著的訴求就是需要承接更多的業務,為團隊、公司創造更大的價值。

  1. 前端工程基本都是基於 Webpack 構建的,這個得用 Node
  2. 頁面、組件也是基於 React、Vue。這塊要做極致的體驗,必然需要做同構,得用 Node。
  3. 微服務的背景下,後端都懶得給你提供視圖對象,一般都是自己在後台根據具體業務進行對象轉換和拼裝。為了純粹前端同學一般會選用 Node,反正性能杠杠的,上生產一點都不慌。並不說前端只會 JS,所以選 Node,反正我見過的會 Java、C#、Golang 的前端不在少數。
  4. 框架層面的成熟度很高。比如:Egg.js,從整體架構到各個模型都非常穩定,日誌信息也非常完整,即使有 Bug 也可能很快的找到,主要是有大牛撐場。

總的來說,Node 給前端帶來了流程上的進化,提供更強的控場機會,也對前端有著更高的要求。

高要求下:

  1. 需要有紮實通用編程基礎,數學基礎,演算法能力。
  2. 需要多語種能力,依我看至少多需要掌握三門:Java、Python、Golang。
  3. 需要比較好的分析、總結等軟能力。


基於前端工程以及後端服務下沉的考慮,web 服務提供 html 主文檔的渲染、API 服務、甚至靜態資源服務(部分資源可以上 CDN),前後端分工會越來越專業化,兩者的職責界限會越來越清晰,後端服務會繼續下沉,前端全鏈路的方案設計也越來越得到重視,用 Node.js 做 Web 服務的中間件,只是其中一個變化,用 php、Java 替換,效果都差不多,有的前端程序員會 php,有的前端程序員會 Java,但是所有的前端程序員都會 JS,自然上手的成本就低了,無論用啥技術,最重要的是關注前端技術範疇的發展趨勢。


贊同 @天豬(劉勇) 說的,其實這一層中間件一直存在,只是在 node.js 出現之前,一直由後端維護。

在快速變化的需求面前,中間件由後端維護,前端使用,會帶來各種溝通問題,雙方都很累。

node.js 出現以後,前端從語言層面消除了寫 web 服務的障礙,而且中間件的邏輯往往也並不複雜,前端完全可以勝任。我使用,我維護,減少了扯皮時間,有利於提升開發效率。


從集成的角度來說。

誰集成,誰負責維護介面層的代碼。是一個不成文的原則。

換句話說,前端是要調用後端API的。這些API由後端人員開發,由前端人員集成到APP或者Web層中。從提高工作效率的角度來說,如果集成的時候發現一些小問題,前端能直接改掉bug是最佳,能定位到bug位置是次佳,只能提供bug report是最糟糕的行為。

用Node.js至少可以讓前端人員做到前面兩條,小Bug直接改掉,比較大的問題能夠定位到具體發生的代碼塊,而不是很尷尬的去告訴後端人員,「又Bug了」,能極大的提升合作效率

很好。


這樣就不用跪求後端幫忙做點東西了。

自己動手,升職加薪。


互聯網公司看規模,沒有超過200人的團隊,不推薦上node中間件,超過且有node後端大牛(注意不是前端js大牛)可以嘗試

另外大家要注意,阿里巴巴技術資源模式和其他大部分互聯網公司不同,他們有大量優秀的架構工程師,冗餘的資源完全能支撐起node中間件的架構開發。(有多少公司請得起幾個「30k每月node主架」來搭一個必要性不是很大的中間件?)

別的公司就要悠著點了,是多請幾個會弄node的後端,還是讓前端團隊抽大量的精英資源轉投後端,無論哪種方案技術成本消耗都很大。

所以我最看不來的就是某些人不看落地場景瞎推廣,請不要把【為什麼需要中間件】和【為什麼需要node做中間件】這兩件事情混起來回答,中間件其實用常用的後端語言實現成本和風險都比node低,技術團隊注意慎被某些技術kpi帶偏。


贊@天豬(劉勇)的回答,BFF 或 GraphQL 都是不錯的中間層解決方案,我想多強調一下後者,其生態更多是圍繞 Node,樓主有興趣可以關注下,詳情可以看下我寫的一篇文章,為了推廣一下 GraphQL, 暫時粘貼過來~

GraphQL 淺談,從理解 Graph 開始

前言

GraphQL is a data query language developed internally by Facebook in 2012 before being publicly released in 2015. It provides an alternative to RESTful architectures. —— from wikipedia.

GraphQL 是 Facebook 於 2012 年在內部開發的數據查詢語言,在 2015 年開源,旨在提供 RESTful 架構體系的替代方案。

掘金翻譯計劃在今年 10 月上線了 GraphQL 中文官網,最近它的討論和分享逐漸增多。其實阿里內不少業務線早有嘗試和分享,聽聞基於 GraphQL 再造了個 TQL。也在其開源的Node.js企業級框架egg中,發布了對應的 plugin。感覺這是一個讓廣大(前端)開發者(重新)認識學習GraphQL的好機會,就讓我們來回顧一下它~

從 Graph 字面開始

先看官網的解釋~

GraphQL 既是一種用於 API 的查詢語言也是一個滿足你數據查詢的運行時。

總結的稍顯高深,簡單拆解一下:

SQL (Structured Query Language) 是結構化查詢語言的簡稱。所以Graph+ QL =圖表化(可視化)查詢語言,是一種描述客戶端如何向服務端請求數據的API語法,類似於 RESTful API 規範。

註:不要聯想到 MySQL、NoSQL,它不是圖形資料庫,比如 Neo4j。

GraphQL 有配套的資料庫服務, graphcool 可以部署在 Docker 上或運行在基於 BaaS(Backend as a Service) 的 Graphcool Cloud。但它不依賴任何資料庫,且能和任何後端(SQL、MongoDB、Redis 等)一起使用,也可以包裹在 RESTful API 之上。

GraphQL 的特性

它定義了一套類型系統(Type System),類似於持續演進(相互借鑒)的FlowTypeScript,用來描述你的數據,先看官網的例子(細節再議)

項目的type
type Project {
name: String
tagline: String
contributors: [User] // 數組表示多個,type 為下面的 User
}
type User {
name: String
photo: String,
friends: [User] // User 的朋友們, type 還是 User
}

接下來你可以把GraphQL查詢語言(Queries)當成是沒有值只有屬性的對象,返回的結果就是有對應值的對象,也就是標準的JSON

請求你所要的數據 // 基於 Queries
{ // 查找 name 為 GraphQL 的 project
project(name: "GraphQL") {
tagline
}
}
得到可預測的結果
{ // 返回 json
"project": {
"tagline": "A query language for APIs"
}
}

雖然 project 在類型系統里定義了三個欄位,但我們(客戶端)只需要 tagline 這個欄位,服務端就只返回這個欄位,而 contributors 里的 User 和其對應欄位,本次查詢(Query)並不關心。這個 demo 看似簡單,其實帶來了很多特性~

  • 強類型GraphQL與 C 和 Java 等後端語言相得益彰,服務端能對響應的形狀和性質做出一定保證,而RESTful是弱類型的,缺少機器可讀的元數據;
  • 分工GraphQL讓服務端定義好支持哪些Queries,把對數據的Query需求下放到客戶端管理,分工明確的同時保持對 API 的聚焦;
  • 分層GraphQLQuery本身是一組分層的欄位,查詢就像返回的數據一樣,是一種產品(工程師)描述數據和需求的自然方式;(PS:部分翻譯的,國外好像都把產品叫做 Product Engineers 而不是 Product Manager。感覺在吐槽的樣子)
  • 預測性GraphQLQuery只返回客戶端要求的內容,沒有任何冗餘(不浪費流量),而且它只有一個介面地址,由此衍生了另一個特性;
  • 兼容性:需求變動帶來的新增欄位不影響老客戶端,服務端再也不需要版本號了,極大簡化了兼容問題;(App 通常是 1-2 周的固定周期發版,在原生應用不強制升級的世界裡,會出現用戶 1-2 年都不升級的情況。 這意味可能同時有 52 個版本的客戶端查詢我們的服務端,而在 Fackbook 中 GraphQL API 曾支持了橫跨 3 年的移動端)
  • 自檢性GraphQL能在執行Query之前(即在開發時)提供描述性錯誤消息,在給定查詢的情況下,工具可以確保其句法是正確有效的,這使得構建高質量的客戶端變得更加容易;
  • Doc MockGraphQL的文檔永遠和代碼同步,開發無需維護散落多處的文檔,調用者也無需擔心過期問題,而且基於類型系統的強力支撐和 graphql-tools,mocking 會變得無比容易。

GraphQL通過它的特性解決了不少問題,當然它不是沒缺點的,這個下期再聊~

我的觀點:當技術棧的缺點因其演進不再明顯之時,必是它優點大放光彩之日 。與此同時GraphQL伴隨著 graph 又帶來了很多新的思考~

GraphQL 的延伸,graphical graph(s)

圖像天然更生動形象易於理解,這意味著GraphQL交互極強的工具和生態,比如:

  • graphiql —— A graphical interactive in-browser GraphQL IDE. 一個讓我們在瀏覽器里用圖形交互的方式探索及書寫GraphQL的 IDE。
  • graphql-voyager —— Represent any GraphQL API as an interactive graph. It"s time to finally see the graph behind GraphQL! 用互動式圖表展示任意的 GraphQL API,總算能看見GraphQL背後的 graph 了!

今年 5 月 22 日 GitHub 發文宣布,去年推出的 GitHub GraphQL API 已經正式可用 (production-ready),並推薦集成商在 GitHub App 中使用最新版本的GraphQL API V4。我們可以用 graphql-voyager 探索(但因 Types、Queries、Mutations 較多數據載入略慢)。

後一個工具可把筆者驚艷壞了,想了解它的生態可以在 awesome-graphql 里尋找。通過它們,所有人都能快速閱讀查詢文檔,調試我們的查詢。

PS:主要是方便調用者和團隊新人的,不過可以思考一個問題,每天是寫代碼還是看代碼多?看介面文檔呢?

另一種思維模式 —— Thinking in graphs

圖是將很多真實世界現象變成模型的強大工具,因為它們和我們天然的心理模型和基本過程的口頭描述很相似。大家應該都沒忘在學校做的資料庫設計,筆者簡單回顧下當年手繪 E-R 圖的過程

  • 一個班級有一個班主任,1:1的關係;
  • 一個班級有多學生多個教師,1:n的關係;
  • 每個學生可以上不同的課程,n:m的關係。

OK,然後大概就成了下面這個樣子,原諒我從百度找的圖:

E-R 圖也稱實體-聯繫圖(Entity Relationship Diagram),提供了表示實體類型、屬性和聯繫的方法,用來描述現實世界的概念模型。

  • 真實世界的數據在本質上是分層的:今天大多數的產品開發涉及視圖層次的創建和操作,這與應用程序的結構保持一致;
  • 我們的開發模式本身也是產品需求驅動的,客戶端關注需求(怎麼取、取哪些),服務端關注能力(可用性、性能),這樣的協作模式更現代更高效;
  • 數據和實體背後的本質也是關係圖:我們的服務端用對象和關係的形式處理,只不過在資料庫用扁平的表格存儲它們;(以前你可以將負責的業務數據通過導出 E-R 圖展現給同事和老闆。如今你還可以通過GraphQL把到對外暴露的API也建模成一張圖。)
  • GraphQL沉澱出來的數據模型(Schema)也可以作為一種給你的團隊(後端前端客戶端甚至產品)及第三方溝通的共同語言,讓大家對這些業務領域的規則形成共同的理解,最終達成共識。

GraphQL的原理、和RESTful的優劣對比以及最佳實踐等等,未完再續~

參考資料 —— 需要翻牆

來自官方的介紹:

GraphQL Introduction

GraphQL: A data query language

來自 InfoQ 的採訪:Facebook開源數據查詢語言GraphQL

來自官方的 Talks:GraphQL: Designing a Data Language

30分鐘內現場演示用Python、Ruby、Nodejs.js,設計3次 GraphQL Sever:Zero to GraphQL in 30 Minutes

歡迎評論交流,也歡迎點贊分享,加速 GraphQL 的傳播~


剛好前幾天看到為什麼要前後端分離的文章,其中講了為什麼服務端不直接用node取代java或者其他語言,而要作為中間件,總結如下幾點:

- java等服務端架構相對已經很成熟了,特別在阿里,此時用node直接取代,成本太高,風險太大,最重要的一點是,直接搶服務端程序員的飯碗,好像不太好

- 服務端直接控制model,service這一層的數據邏輯,不用考慮controller那一層的數據展現形式,而前端直接使用node獲取數據,並使用模板渲染到頁面,這樣前後端的職責和分工更加明確,代碼也會更好維護。

- node的底層就是c++,可以和一些服務端語言更加無縫地結合。

粗略總結的幾條,建議去看看淘寶團隊的文章,裡面的前後端分離有幾篇乾貨滿滿的總結~


https://zhuanlan.zhihu.com/p/32487533?utm_source=com.android.mmsutm_medium=social


簡單的事情怎麼做都可以。在保證解決問題的前提下,技術團隊喜歡怎麼來就怎麼來。


其實沒什麼好處

只是因為大部分前端都會node 所以順手就用了

但這一層你其實用php 用java等去做 也都是可以的


nodejs做為中間層有很多好處:

  1. 服務的聚合。前端往往是跟業務更加靠近的,所以由前端去控制業務流程是一個更好的選擇,前端可以在node這一層根據自己的需求對後端更細粒度的介面進行組合返回給瀏覽器進行渲染,相當於把之前後端的controller層前移給了前端,而後端可以更集中的去提供更加貼近數據粒度的介面。
  2. 模板的渲染,避免SPA中SEO的問題
  3. MOCK層,前端開發的mock放在這一層做會更方便。
  4. 。。。


好處就是,前端可以自己控制介面欄位,不用和後端去扯皮。發現問題,能很快定位前端問題還是後端問題,還能做監控,用戶從進來到走全部記錄。


mark一下,慢慢補充。

  1. 大項目中API調度更加靈活,原來用nginx總是怕正則寫錯。
  2. 測試中mock更方便。
  3. 前後端扯皮減少。talk is cheap, show me your code。


nodejs做中間層,前後端分離更徹底,甚至一些短暫使用的數據調用功能,前端直接使用redies和node做介面和臨時數據,自己開發。而且對於後端來說,有時候加個欄位還得影響資料庫的結構,這時候就太過浪費資源了。所以,前端部署時,用node搭建運行環境,和後端部署完全解耦。


說幾個細節吧:

  1. 使用新的 Fetch 介面,發送一個 http 請求可以寫得極其簡潔和易讀。用 java 就呵呵了。
  2. 並行 http 請求,Node.js 寫起來都很容易,用 Promise.all 就行了,結合 async/await 寫負載邏輯也沒有問題。用 java 寫並行發送請求也呵呵了。
  3. Node.js 相比 Java 輕量級多了,10 個 Node.js 進程也沒一個 JVM + Tomcat 佔用的內存多。


有利於前端同學完成kpi


推薦閱讀:

前端構建工具webpack有什麼缺陷?
DocumentFragment真的能提高 JS 動態添加 DOM 的性能嗎?
如何優化vue的內存佔用?
能否用 JS 實現一個 CSS 解釋器?
如何理解 Facebook 的 flux 應用架構?

TAG:Web開發 | JavaScript | Nodejs |