簡體   English   中英

應該如何設置針對高需求應用程序的node.js堆棧?

[英]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監控工具。

所以,我想知道一些應對這些問題的路線圖,也許應該提供更詳細的信息,到目前為止,我可以說當沒有太多用戶時,應用程序看起來很穩定。

要考慮哪些主要因素和設置?

到目前為止,我知道我應該做的 ,但我不知道有關細節或怎么樣了

恕我直言:

  1. 盡可能緩存。
  2. 延遲MongoDB寫操作。
  3. 具有更高寫入需求的單獨Mongo數據庫。
  4. 虛擬化?
  5. 調整節點設置。

在優化代碼時,我發布了另一個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本周性能提示:堆分析

第三,嘗試Node.js聚類MongoDB分片

最后,檢查您是否使用或可以切換到MongoDB 3.x. 通過從2.x升級到3.x,我們觀察到了一些顯着的性能提升。

基本上大多數要點已經存在於答案中。 我只是總結一下。

要優化您的應用程序,您可以執行幾項主要操作。

  1. 嘗試將表單node.js移動到io.js它仍然有更好的性能和最新的前沿更新。 (但仔細閱讀有關實驗性功能的信息)。 或者至少從node.js v10v12 有很多性能優化。

  2. 避免使用使用I / O操作或使用大量數據的同步函數。

  3. 從一個節點進程切換到集群系統。

  4. 檢查應用程序是否存在內存泄漏。 我正在使用node.js v12 memwatch-nextnode.js v10 memwatch

  5. 盡量避免將數據保存到全局變量

  6. 使用緩存。 對於全局可訪問的數據,您可以使用RedisMemcached也是一個很棒的商店。

  7. 避免與Promises使用async 兩個lib都在做同樣的事情。 所以不需要同時使用它們。 (我在你的代碼示例中看到過)。

  8. async.waterfallasync.parallel方法結合起來可以完成。 例如,如果您需要從僅與用戶相關的mongo中獲取一些數據,您可以獲取用戶,然后並行獲取所需的所有其他數據。

  9. 如果您使用sails.js確保它處於production模式。 (我假設你已經這樣做了)

  10. 禁用所有不需要的掛鈎。 在大多數情況下, grunt hook是無用的。如果你的應用程序中不需要Socket.io - 使用.sailsrc文件禁用它。 就像是:

    {“generators”:{“modules”:{}},“hooks”:{“grunt”:false,“sockets”:false}}

另一個可能被禁用的鈎子是: i18ncsrfcors 但前提是您不在系統中使用它們。

  1. 禁用無用的全球化。 config/globals.js 我假設默認情況下可以禁用_asyncservices 僅僅因為Sails.js使用舊版本的lodashasync庫,新​​版本具有更好的性能。

  2. 手動將lodashasync安裝到Sails.js項目中並使用新版本。 (看點11)

  3. 在將結果返回給用戶之后,可以進行一些“寫入mongo”操作。 例如:您可以調用res.view()方法,該方法將在Model.save()之前向用戶發送響應。但是BUT代碼將繼續運行所有變量,因此您可以將數據保存到mongo DB。 因此用戶在寫操作期間不會看到延遲。

  4. 您可以使用像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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM