1. 程式人生 > >蘇寧的Node.js實踐:不低於Java的渲染效能、安全穩定迭代快

蘇寧的Node.js實踐:不低於Java的渲染效能、安全穩定迭代快

前端 Node.js 的使用場景大多集中在前端工具上,當前的前端主要把它定位為輔助。蘇寧易購使用 Node.js 作為前後端分離的主要手段,經歷了從技術引進到全面開花,從邊緣功能到核心業務,從紛亂到穩定的過程。同時 Node.js 作為新引入的技術,與公司原有架構融合銜接面臨著怎樣的挑戰?以下是蘇寧技術總監 禹立彬老師在 7 月深圳 ArchSummit 全球架構師峰會上的演講整理。

在蘇寧引入 Node.js 之前,蘇寧已經有了成熟的技術架構。

蘇寧的技術架構,由蘇寧雲、基礎支撐、後臺、中臺和前臺組成。蘇寧雲主要為業務開發提供雲服務。基礎支撐,包括資料連線協議、防火牆、日誌、中介軟體、簡訊等。在蘇寧雲和基礎支撐之上,業務開發分為前中後臺。而 Web 前端,主要集中在前臺上。包含 PC 端、移動 WAP 端等。

Node.js 的應用非常廣泛,在不同的公司,可以用作微服務,也可以用來提供 API,蘇寧引入 Node.js,最主要的,是用 Node.js 做中間層,當做一個 Web 渲染器,渲染頁面,來實現前後端分離。

Web 前臺系統

在前臺系統裡,以前的開發模式,完全是 Java 技術棧。Java 系統,分為 Java Service 伺服器,和 Java Web 伺服器,Java WEB 伺服器讀取 Java Service 伺服器提供的介面,通過 FTL 模板來渲染頁面。

引入了 Node.js 以後,蘇寧研發團隊的目標是使用 Node.js 替代 Java Web 伺服器的渲染位置,使用 Node 模板,去替換 Java 模板,去除了模板檔案誰寫這樣的模糊地帶,讓後端的 Java 工程師,只寫 JSON 服務,實現前後端分離。

在應用前後端分離後,顯式的獲得了一些好處,Node.js 系統的迭代速度優勢明顯強於 Java Web,包括由於 Node.js 的輕量,帶來的快速開發快速迭代,以及減少了前後端溝通上的“聯調”時間成本,加快了專案的開發速度。同時,減少老專案裡 Java 後臺工程師寫頁面導致的一些 BUG,提高了程式碼質量。

由於以上的這些優點,現在蘇寧易購的 Node.js 專案越來越多,逐漸深入到核心業務。最早期,蘇寧只是在使用者體驗收集這樣的邊緣頁面使用 Node.js,現在已經在海外購,小程式,大聚惠,我的易購,香港站,購物車等業務中都廣泛的使用了 Node.js,這樣就不可避免的直面更多的技術挑戰。

Node.js 如何融入已有技術架構

當只是作為邊緣業務時,Node.js 專案尚可以通過一些臨時方案,或者引入試點,來逃避,但是深入核心業務後,Node.js 專案很快,就會被納入總的技術架構裡。

這是一張比較簡單的 Node.js 應用部署圖。一個 Node.js 應用被訪問時,會使用公共的負載均衡,使用應用防火牆,當達到 Node 伺服器時,要使用物理機和虛擬機器,Node 伺服器要訪問 Java Service 伺服器也需要連線協議

最簡單的是 IaaS,在這個層級上,Node 可以完全可以複用蘇寧雲成熟的網路,儲存,物理機,虛擬機器等資源。

到了虛擬機器這個層級,在這幅 Node.js 伺服器圖上,可以看到單臺 Node 伺服器,有一個 Nginx,來做訪問的 accessLog 和做反向代理到本機的 Node.js 應用埠,這臺機器上同時安裝了 PM2,來啟動多個 Node 應用,對應不同的埠,來提供對外服務。

在 PaaS 這個層級上,蘇寧也儘量沿用了公司已有的技術資源。比如在作業系統方面,使用了 RedHat Linux,儘量向已有技術架構靠攏。

在伺服器的 Node.js 版本上,在去年年初的版本是 Node 6.9,去年年底已經將 Node 版本升級到 Node 8 了,研發團隊堅持使用 LTS 版本的 Node.js。到 Node 有大版本更新時,同時更新 PaaS 平臺的 Node 版本。

在 Nginx 上,選擇的也是已有的通用 Nginx 版本,Node 伺服器對 Nginx 版本要求不嚴格,Nginx 監聽多域名的 80 埠後,反向代理到 Node 埠就好。

Redis 的情況要麻煩一些,Node.js 由於程序的原因,遇到 Session 這樣需要多程序或者多伺服器直接共享資料時,就必須藉助 Redis。很顯然,Java 體系內,並沒有對應的 Node 版本的 Redis 客戶端,於是蘇寧自己編寫了一個基於 ioredis 的 Redis 客戶端,來滿足需求。

在 DB 上,蘇寧則遵循總的技術架構要求,Node 伺服器不直連 DB,要獲取資料時,永遠是連線 Java 服務。

監控報警

解決了伺服器環境後,Node 也要接入日誌服務和報警系統。通過配置 Nginx 日誌格式和 PM2 的日誌外掛 pm2-logrotate 來將日誌格式符合總技術架構的日誌平臺要求,並在日誌平臺上配置 4XX 和 5XX 報警,並且針對 Node 本身的一些特色,編寫 PM2 外掛,監控 Node 程序異常,併發送異常到蘇寧內部的即時通訊團建上。

CI/CD 釋出系統

伺服器好了,程式碼編寫好了,也需要釋出。利用公司的統一發布平臺,在平臺上新建了 Node.js 標準釋出,統一了 Node 程式碼包打包方案,統一了程式碼部署目錄,統一從內部私庫安裝 NPM 包,統一了應用重啟的方法。

除此之外,為了滿足公司的總技術架構要求,蘇寧研發團隊還編寫了基於 Node 的呼叫鏈監控元件,可以適配 ESB/RSF 通訊協議的客戶端元件,以及適合 Varnish 下的 KOA,EXPRESS 中介軟體。

技術挑戰

解決了技術架構要求方面的問題,Node 可以正規軍上崗了,核心業務又會帶來更高的技術要求。

以大聚惠頁面為例,大聚惠是蘇寧的一項營銷業務,很多優惠活動,是通過大聚惠的名義放出的,因此業務非常重要。又因為運營需要,總是在凌晨 0 點,貨品上新,要求此時頁面不能有快取,而且由於電商業務的特殊性,會遇到 618,818,雙十一這種半夜搶購的情況,因此全靠伺服器硬扛流量洪峰,這就對應用效能,提出了很高的要求。

這個專案上線的時候,恰好是升級了 Node 8,研發團隊把框架從 express 轉換為 KOA,寫了一樣的程式碼,壓測時,4C4G 單機才 40TPS,而同樣的 Java 系統,單機約為 200TPS,效能差距明顯。

併發效能優化之路

首先考慮是快取問題,經過排查,在 KOA 下,並不會預設開啟,模板快取,導致每次總是去硬碟讀模板,當然快不了。果斷優化,TPS 上升為 120TPS,依然差距明顯。Express 框架中會預設開啟模板快取,而預設的 KOA2 並不會開啟,首先開啟模板快取效能提升明顯。

另外,通過 CPU-PROFILER 排查,發現路由消耗的時間挺多,匹配字串路由,和匹配正則路由,時間消耗差距明顯,於是將路由排序,優先選擇字串路由,將 TPS 推向 140TPS。

再查,為了減少併發,除渲染模板外,Node 還在業務裡,合併了靜態資源地址,並且中介軟體載入的策略也可以優化,去除掉一些可以不用的中介軟體。比如只用 EJS 模板,那麼就去除其他模板引擎的支援,通過這些優化,講 TPS 提升到了 180TPS。

TPS 沒有提升後,再排查,發現 include 函式執行時間很長,發現 ejs 原始碼處理 include 時,總是去硬盤裡查詢是否有被 include 的模板檔案,而這個頁面是多人開發,include 使用非常頻繁,再進一步優化,終於達到了 220TPS。

不低於 Java 的渲染效能

最後,獲得了不低於 Java 的渲染效能。很多文章部落格對待 Node 渲染頁面時會兩級分化,一極認為 Node 不適合做這種 CPU 密集型操作,另一極就是不斷宣揚 Node 效能強勁,但是在蘇寧實際的應用中,從來沒想過超過 Java 多少倍的效能,事實上也是。Node 的基礎效能略高於或者持平於老的 Java FTL 渲染器。

安全與穩定

除了效能,安全與穩定也是重點需要的環節。針對 Node.js 來說,客觀的說,安全文件方面是不如 Java 等語言的。

一方面是最後後來者,追趕前輩需要時間,另一方面也是 Node.js 的固有問題。Node.js 是單執行緒的,程式碼報錯會導致程序退出,在 Node 生態早期,會直接導致 Node 訪問掛掉;

第二個,JS 是弱型別語言,很多人認為弱型別的語言寫的沒有安全感,沒有程式碼檢查;

第三個,NPM 很好,開源社群很強大,元件很多很方便,但是對於企業使用者來說,都抵不過一個 left-pad 事件,公網的 NPM 包也會良莠不齊,如果出現了安全漏洞,影響就會非常大。

問題如何解決

NPM 包策略。蘇寧使用公司的私有 NPM 倉庫來安裝 NPM 包,避免外網擾動,導致無法安裝問題。在核心業務中,限制使用不流行的 NPM 包,減少風險。在 package.json 裡的包版本,使用確定的版本,不用符號,減少包升級導致的 bug。對於自己開發的 NPM 包,嚴格進行單元測試及安全測試,進一步的減少風險。

使用 PM2。針對 Node 程序掛掉的問題,蘇寧使用了留下的 PM2,來保證 Node 程序的存活。當 Node 程序掛掉時,PM2 會重啟他們。感謝 PM2,通過它,也實現了釋出的無縫重啟,保證了平滑升級。

Node.js 系統的相對安全

安全上,蘇寧強制了所有的 Node 系統加入應用防火牆 WAF,使用基於 KOA 的安全中介軟體 XSS,儘量使用精確匹配的路由,減少注入。並在上線前,做完全的安全測試,實現 Node 系統的相對安全。

前端團隊的挑戰

另一方面,由於引入了 Node,前端工程師對 Node 相關的知識瞭解較少,也會犯一些低階錯誤,技術挑戰也是非常大的,知識要求被增加了很多。

為了解決這個問題,蘇寧成立了專門的前端架構組,為各業務團隊保駕護航。在釋出,配置,安全監測等各個方面幫助業務開發團隊。

全棧技能提升計劃

並在工作中,加強 Node 技能培訓。梳理出容易犯的低階錯誤,比如 promise 不寫 catch,某個條件分支裡,不寫請求返回,通過宣講的方式,提高程式碼質量,並組織程式碼評審等活動,進一步的提升技術能力。

Node.js 的影響

可以說,進入了核心業務,前端團隊遇到的挑戰是越來越大的,同時,Node 的推進也帶來了一些正面負面的影響,時間有限,不做太多的講解,僅舉幾個方面。

第一個方面,專案更敏捷了,Node.js 釋出不涉及後臺服務,即使釋出出了小問題,也可以快速再次釋出和回滾,因為 Node.js 系統其實是可以 24 小時釋出,對業務支撐顯然更迅速敏捷。運營商務。都顯然的歡迎 Node。

同時,Node 的引入,也對前端團隊帶來了影響。Node 的引入帶來了前端工作量的增加,需要更多的前端工程師投入。

另一方面,也顯著的提高了團隊的技術活力,在團隊內部颳起了全棧風,技術更活躍,解決問題的方案也更多了。

最後還有一些小型的負面影響,定位 bug 時,時間有所增加。需要查 Node 的問題,還是 Java 的問題;另一方面,訪問效能因為 HTTP 的問題,略微增加了幾毫秒。當然這對於前面的好處來講都是可以接受的。

 

 

本次給大家推薦一個免費的學習群,裡面概括移動應用網站開發,css,html,webpack,vue node angular以及面試資源等。
對web開發技術感興趣的同學,歡迎加入Q群:943129070,不管你是小白還是大牛我都歡迎,還有大牛整理的一套高效率學習路線和教程與您免費分享,同時每天更新視訊資料。
最後,祝大家早日學有所成,拿到滿意offer,快速升職加薪,走上人生巔峰。