歡迎光臨
每天分享高質量文章

美團酒店Node全棧開發實踐

前後端分離的背景

“前後端分離”顯然已不是什麼新鮮的話題,Zakas在2013年10月份就曾發表過一篇博客《Node.js and the new web front-end》討論Node背景下新時代的前端。毫無疑問,Node的出現給JavaScript語言帶來了新的生機,也使得前端開發者有了更多的可能性。

前後端分離錶面上看似乎是一場“圈地運動”,但實質上前後端分離是為瞭解決以往開發樣式的一些詬病和痛點,同時也是迎合大的行業趨勢的明智之舉。我所在的美團酒店事業部去年7月份成立,新的業務、新的開發團隊,這一切使得我們的前後端分離推進的很徹底。截至目前,前端承載的所有業務和線上服務都是基於Node,生產環境已經有近20台服務器。如此帶來的全新前後端協作方式能夠讓專業的人做專業的事,無論前端後端都能較之前更專註在自己擅長的方面。

開發樣式、技術棧

傳統的開發樣式只需要專註在多終端的呈現上(瀏覽器、WebView)。而現在,瀏覽器只是前端的其中一環,延伸出來的還有Node端的架構、服務的運維能力等。上圖是我們目前的服務架構:Nginx位於Node服務之前,用做負載均衡、服務調度、Gzip壓縮等。之後便是Node服務,我們通過PM2.5進行Node服務的Cluster部署和負載均衡(充分利用多核優勢),同時作為輕量的中間層,負責路由、Controllers、Views、以及視圖的渲染,資料的獲取通過RESTful的API接口使用JSON格式交互。而後端則只需要負責業務邏輯、資料儲存、Models,併為前端提供JSON資料即可。

這樣改變之後,Node端可以進行首屏渲染等頁面加載方面的優化,頁面渲染出來之後後續的交互、渲染都交由瀏覽器端的JavaScript代碼來完成,Node端的模板和瀏覽器端的模板大部分情況下都是相同的,所以我們需要考慮模板重用的問題。我們用Juicer替換了Express框架預設的模板引擎,Juicer是一個高效、輕量的前端 (Javascript) 模板引擎,效率和易用是它追求的標的。除此之外,它還可以運行在 Node.js 環境中。通過Juicer,可以解決Node端和瀏覽器端的模板、Helper復用問題。而且基於前後端分離的工程架構下,前端的代碼倉庫和後端隔離,前端獨立負責前端靜態資源檔案、模板檔案、Controller的維護和發佈。

按照這樣重新定義前後端分工之後,前端可以做的事情較以往更多了,比如微信SDK的接入,因為微信JS SDK的使用需要在服務端進行簽名,所以現在我們不需要後端介入,前端完全可以獨立完成微信SDK的接入。此外像我們內部和商家端SSO登錄邏輯的接入都完全由前端獨立完成。

技術選型的思考

對於前端的技術選型,我們始終保持理性、擁抱的態度。我們不會為了盲目求新而引入新的技術,技術選型是針對我們目前大團隊的場景,為瞭解決以往協作過程中發現的一些痛點和不足。比如引入Node是為了改進前後端的工作流和效率,提升前後端的開發體驗。再比如目前我們專案中採用的Angular、React也是針對特定的業務場景,為了提升開發效率、增強代碼的可維護性。在我們的業務應用中,面向商家、後臺的一些增刪改查系統,Angular能夠顯著的提升開發效率,而React我們目前只是在面向用戶的PC端專案中在做一些嘗試和實踐。

帶來的挑戰

這樣的分工和架構樣式在給前端帶來更多可能性、更多便利的同時,也帶來了不小的挑戰,相比傳統的前端角色而言,我們需要更多的關註線上服務的狀態,行程記憶體占用、CPU占用的詳細狀況,以及線上異常的監控等。在我們擁抱Node的同時,對前端的能力要求是更上一階的。一段看起來正常的JS代碼,在瀏覽器端和在Node端兩種不同的運行環境下,就可能會暴露出一些以往關註不到的問題,比如記憶體泄露:一個閉包或者一個用於快取資料的物件,跟瀏覽器不同,Node對記憶體泄露十分敏感,因為線上應用有成千上萬甚至百萬計的流量,所以哪怕是一個位元組的記憶體泄露也會造成記憶體堆積,從而導致垃圾回收過程耗時增加,應用響應緩慢,知道行程記憶體上限溢位,應用重啟或崩潰。

記憶體泄露問題的定位

以下是我們在生產環境遭遇的一個案例:最近發現線上服務的記憶體占用在服務重啟後會呈線性的增長,行程啟動18小時後,記憶體就已經占用接近1.6G左右,之後不久便會超過V8的記憶體限制導致服務重啟。從圖中可以看出,在修複之前記憶體使用情況一直在隨時間進行周期性的波動,波動的原因就是線上Node行程不斷的重啟導致的。

眾所周知,在V8的垃圾回收機制下,一般的代碼很少出現記憶體泄露的情況,但是一旦出現記憶體泄露往往較難排查。但造成記憶體泄露的本質原因只有一個,就是應當回收的物件沒有正常被回收,變成了老生代中的常駐物件。好在借助一些常見的排查工具可以幫助我們定位記憶體泄露的具體原因:

– v8-profiler

– node-heapdump

– node-mtrace

– dtrace

– node-memwatch

這裡我們使用node-heapdump來在模擬訪問的條件下生成堆記憶體的snapshot,並通過Chrome的開發者除錯工具對生成的snapshot檔案進行分析。通過對比服務剛啟動時以及使用AB模擬併發訪問一段時間後的heapdump信息可以比較容易的定位到記憶體泄露的問題點:是因為Juicer預設開啟了cache,會預設對編譯後的模板進行快取,因此隨著訪問的增長和併發請求,cache物件會持續增長且不被回收,於是關閉cache並重新部署上線後線上恢復正常。

由於在瀏覽器的場景中運行時間短,且運行在用戶的機器上,即便記憶體使用過多或者記憶體泄露,也只會影響到用戶的終端。而且運行時間短,隨著行程的退出,記憶體也會隨之釋放,幾乎沒有太多記憶體管理的必要。但在Node端同樣的代碼就可能會暴露出問題。

線上服務的運維和監控

前後端分離除了意味著代碼倉庫的分離、開發協作的分離之外,還涉及到線上服務的獨立發佈和單獨部署。與之俱來的當然是前端如何更好地對線上服務進行更細粒度的運維和監控,我們的SA會更多的關註線上服務的整體指標和可用性,而前端更希望能夠細粒度的瞭解線上Node的行程狀態以及異常情況。

PM2是一款優秀且開源的Node行程管理工具。我們在PM2的基礎上做了一些改造,同時在雲端部署了資料收集、資料實時獲取的服務,從而形成了我們目前已經應用到線上的Node部署監控平臺PM2.5,它可以將線上Node服務行程級別的細粒度信息聚合在雲端進行處理和可視化展現,PM2.5能夠監控Node Server和行程的各項指標狀態,且可以配置報警併在各終端(Web、iPhone、Apple Watch)展示。

PM2.5的服務架構

簡單介紹下PM2.5的服務架構:生產環境的Node服務通過PM2.5 CLI進行部署,PM2.5 CLI會持續不斷的將Node行程的各項資料上報到PM2.5的雲端。雲端收到上報的資料後會對原始資料進行處理並儲存至MongoDB。而Web端和iOS應用都會通過WebSocket服務從服務端獲得實時的資料流,然後通過前端進行可視化的信息展示。

PM2.5的內部實現

當Node行程通過PM2.5啟動時,PM2.5 CLI會同雲端服務進行握手,握手成功後才會源源不斷的進行資料的上報。上報時首先會將資料進行AES256加密,然後使用TCP通信將資料上報到服務器,這裡用到了開源的Axon,雲端服務器收到資料後會將資料入庫儲存到MongoDB中,同時會進行監控報警的掃描,如果當前資料符合用戶訂閱的監控報警條件,則會通過雲端的Push服務向iOS客戶端推送報警信息。雲端同時運行WebSocket服務,為多個終端(Web平臺、iOS應用)提供實時資料的推送。

這裡值得一提的是,PM2.5的客戶端是基於React-Native開發,目前已經提交Apple Store正在審核,審核通過後就可以從Apple Store中下載到了,客戶端提供了服務和行程基本指標的查看,同時可以配合Web平臺的監控報警設置實現7×24小時對服務的監控。

其它監控設施的接入

為了確保線上服務的可靠、穩定,我們還接入了其它一些監控設施和日誌平臺,便於對線上的錯誤和訪問日誌進行追蹤、分析和定位處理。

Zabbix

Zabbix是一種分佈式系統監控以及網絡監控功能的企業級開源中間件,主要是被運維使用。Zabbix主要用於對服務進行心跳檢測、監控服務的各項指標,當某些指標異常或超過設定的閾值時進行短信、大象、郵件的報警。

Sentry 錯誤日誌收集

Sentry是一個錯誤日誌服務器,可以將程式錯誤的詳細情況集中捕獲。而且提供各種常見語言的SDK供業務接入。但Sentry在服務器端會有採樣,一般不能替代實時錯誤日誌報警的監控。

日誌監控平臺

日誌監控平臺是美團內部的一個日誌收集系統,目前美團統一使用flume收集日誌,flume具有接收scribe格式日誌的能力,而日誌監控平臺也是以scibe格式日誌來收集。日誌在整個收集流程中以兩種形式存在,分別是原始日誌和解析後的日誌。目前我們使用日誌監控平臺主要用於將訪問日誌的格式化資料上報,之後就可以通過Hive/Presto對訪問資料進行查詢了。

性能監控平臺

性能監控平臺為美團各平臺和產品線提供簡單易用的、端到端的性能資料服務。同時也提供了各種常見語言的SDK供業務接入。主要用於分析Node端的接口響應,以及瀏覽器端的頁面載入性能。

小結

以上是美團酒店前端在應用Node進行全棧開發的過程中摸索前行的一些心得,也是引子,主要介紹了我們酒店事業部的前後端分離架構,線上記憶體泄露問題的排查,和所使用的Node服務監控平臺PM2.5,後續我會分享更多我們的Node方面的一些實踐,以及PM2.5監控平臺的背後實現,希望能對你有所幫助,也歡迎大家能夠參與進來共同交流前後端分離和Node相關的技術點。

來自:美團技術博客 – 郭凱

鏈接:http://tech.meituan.com/node-fullstack-development-practice.html

赞(0)

分享創造快樂