[英]How should a node.js stack for a high demand application be setup?
我目前正在研究超過25000人使用的Node.js堆棧應用程序,我們特別使用Sails.js框架,我們得到的MongoDB應用程序運行在具有30GB RAM的EC2實例上,數據庫運行在Mongolab上基於AWS的集群在EC2所在的同一區域中。 我們甚至有一個1.5GB的Elastic Cache Redis實例用於存儲。
因此,我們面臨的主要和巨大問題是延遲 。 當我們達到請求應用程序的並發用戶的峰值時,我們得到多個超時和sails應用程序達到超過7.5GB的RAM,對API的HTTP請求需要超過15秒(這是不可接受的),甚至當獲得502和504響應時nginx的。
我可以注意到Mongo寫入操作是我們的主要延遲問題,但是當存在需求峰值時,即使GET請求也需要很長時間。 我無法訪問生產服務器,我只有pm2(實際上很棒)和New Relic警報的keymetrics監控工具。
所以,我想知道一些應對這些問題的路線圖,也許應該提供更詳細的信息,到目前為止,我可以說當沒有太多用戶時,應用程序看起來很穩定。
要考慮哪些主要因素和設置?
到目前為止,我知道我應該做的 ,但我不知道有關細節或怎么樣了 。
恕我直言:
在優化代碼時,我發布了另一個stackoverflow問題,其中包含一個我正在遵循的代碼模式示例。
您對生產應用有何建議和意見?
首先,確保您沒有使用同步I / O. 如果您可以在io.js
運行,則會有--trace-sync-io
標志( iojs --trace-sync-io server.js
),如果您使用具有以下控制台警告的同步代碼,它將發出警告: WARNING: Detected use of sync API
。
其次,找出你的RAM使用率如此之高的原因。 如果是因為大量數據被加載到內存中(XML解析,MongoDB返回的大量數據等),您應該考慮使用streams
。 如果您的內存使用率非常高,V8垃圾收集(在Node.js
/ io.js
使用的Google的JavaScript VM)可能會導致速度減慢。 更多信息: Node.js本周性能提示:管理垃圾收集和Node.js本周性能提示:堆分析
最后,檢查您是否使用或可以切換到MongoDB
3.x. 通過從2.x升級到3.x,我們觀察到了一些顯着的性能提升。
基本上大多數要點已經存在於答案中。 我只是總結一下。
要優化您的應用程序,您可以執行幾項主要操作。
嘗試將表單node.js
移動到io.js
它仍然有更好的性能和最新的前沿更新。 (但仔細閱讀有關實驗性功能的信息)。 或者至少從node.js
v10
到v12
。 有很多性能優化。
避免使用使用I / O操作或使用大量數據的同步函數。
從一個節點進程切換到集群系統。
檢查應用程序是否存在內存泄漏。 我正在使用node.js v12
memwatch-next和node.js v10
memwatch
盡量避免將數據保存到全局變量
使用緩存。 對於全局可訪問的數據,您可以使用Redis
或Memcached
也是一個很棒的商店。
避免與Promises
使用async
。 兩個lib都在做同樣的事情。 所以不需要同時使用它們。 (我在你的代碼示例中看到過)。
將async.waterfall
與async.parallel
方法結合起來可以完成。 例如,如果您需要從僅與用戶相關的mongo中獲取一些數據,您可以獲取用戶,然后並行獲取所需的所有其他數據。
如果您使用sails.js
確保它處於production
模式。 (我假設你已經這樣做了)
禁用所有不需要的掛鈎。 在大多數情況下, grunt
hook是無用的。如果你的應用程序中不需要Socket.io
- 使用.sailsrc
文件禁用它。 就像是:
{“generators”:{“modules”:{}},“hooks”:{“grunt”:false,“sockets”:false}}
另一個可能被禁用的鈎子是: i18n
, csrf
, cors
。 但前提是您不在系統中使用它們。
禁用無用的全球化。 在config/globals.js
。 我假設默認情況下可以禁用_
, async
, services
。 僅僅因為Sails.js
使用舊版本的lodash
和async
庫,新版本具有更好的性能。
手動將lodash
和async
安裝到Sails.js
項目中並使用新版本。 (看點11)
在將結果返回給用戶之后,可以進行一些“寫入mongo”操作。 例如:您可以調用res.view()
方法,該方法將在Model.save()
之前向用戶發送響應。但是BUT代碼將繼續運行所有變量,因此您可以將數據保存到mongo DB。 因此用戶在寫操作期間不會看到延遲。
您可以使用像RabbitMQ這樣的隊列來執行需要大量資源的操作。 例如:如果您需要存儲大數據集合,您可以將其發送到RabbitMQ
並將響應返回給用戶。 然后在“后台”流程廣告商店數據中處理此消息。 它還可以幫助您擴展應用程序。
對於Mongodb,您可以使用mongtop查看哪些數據庫是有爭議的,每個數據庫鎖定使用2.2+,如果數據庫已寫入,那么繁重的工作負載讀取將受到影響,因為mongodb正在使用writer greedy locks
對於node.js,您可以檢查是否存在任何可以解釋API請求延遲的事件循環延遲
(function getEventLoopDelay() {
var startTime = Date.now();
setTimeout(function() {
console.log(Math.max(Date.now() - startTime - 1000, 0));
getEventLoopDelay();
}, 100);
})();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.