【问题标题】:How do you optimise memory/cpu on NodeJS / Express? [closed]您如何优化 NodeJS / Express 上的内存/cpu? [关闭]
【发布时间】:2016-01-20 19:51:07
【问题描述】:

我有一个基于 Express 构建的 Node 应用,它使用网络爬虫来加载和解析数据。

我已经阅读了很多关于 NodeJS 的可扩展性和能够处理大量并发连接的文章,但是当您运行网络爬虫(发送 1000 多个并发请求)时,我觉得事情开始有点崩溃了。

在运行时,我的服务器对其他 API 请求没有响应,并且同时运行多个实例会导致事情慢如蜗牛。

我找不到任何关于限制是什么、应该是什么、我应该汇集多少个请求等等的文档。

我是否应该将抓取工具的请求限制为每秒 10 个?每秒 100 个?每秒1000?或者我是否可以增加分配给我的 VPS 上的节点进程的 CPU/内存量?

编辑:对于那些因为这个问题过于基于意见而投票结束的人,这就是我要问的具体内容:

  1. Express 应用程序可以同时执行多少个 HTTP 请求,然后才会开始发挥性能
  2. 增加应用程序可用的内存/cpu 是否有任何帮助?

【问题讨论】:

  • 当我们说 NodeJS 可以处理 1000 多个并发请求时,它们本质上是非阻塞请求,即不是非常占用 CPU 的任务。如果网络爬虫是 CPU 密集型任务,最好在这些服务器上使用负载均衡器的节点服务器集群。
  • @AmanGupta 太棒了,这些是我以前从未听说过的术语。您能否推荐一些资源来了解有关负载平衡和集群工作的更多信息?
  • 你可以从这个开始:sitepoint.com/…

标签: javascript node.js express web-scraping vps


【解决方案1】:

有很多不同的方法可以评估 Node 的性能。节点是usually recommended for I/O bound workloads as opposed to CPU bound workloads,尽管它运行的 V8 引擎在不断改进。

让 Node 执行的一个重要方面是以启用其“非阻塞”执行模型的方式进行编码。这意味着对控制流使用回调函数和/或承诺,而不是传统的同步方法。如果您不编写异步代码,节点将阻塞,因为事件循环将挂起需要任何大量时间才能完成的代码。

I/O 可以(并且应该)与 Node 异步,但是 CPU 繁重的活动(例如在抓取后解析 .xml)不能(或程度不同),因此事件循环最终会挂起完成每个长 CPU 任务。

要将其应用于您的特定用例并解决性能问题,如果您发布一些抓取工具的请求代码可能会有所帮助。

注意:如果您已经理解这些概念并且这低于您的技能水平,我提前道歉。

我已经包含了一个 sn-p 代码,它启动一系列对一系列 .xml 资源的请求并将响应打印到控制台。如果您运行此代码,您会注意到打印通常会“乱序”发生,因为每个请求可能需要不同的时间。为http.request() 方法提供回调而不是使用同步版本的优点是,一旦请求开始,您的应用程序可以继续运行并接受新的请求。该工作可以随着 Node 事件循环的每次完成而逐步完成。

通过使用专门处理请求的库,可以大大简化这段代码 sn-p。一个众所周知的称为request(恰如其名),它可以帮助您的代码更简洁。

附带说明,在您的项目中大量使用console.log() 可能会导致性能问题。

var http = require('http');

function getData(index) {
  var options = {
    'hostname' : 'example.com',
    'path' : '/data' + index + '.xml',
    'method' : 'GET'
  };    
  var req = http.request(options, function(response) {
     var fullText = "";
     // listen for incoming data and add it to existing data
     response.on('data', function(more) {
         fullText += more;
     });
     // when request is complete, print it
     response.on('end', function(done) {
         console.log(fullText);
     });
  });
  req.end();
  // Do not fail silently, show error details
  req.on('error', function(e) {
     console.error(e);
  });
}

for(var i = 0; i < 1000; ++i) {
    getData(i);
}

【讨论】:

  • 这是很棒的伙伴,无需道歉,因为这正是我所希望的。虽然我变得更好并且理解了 Node 中的阻塞/非阻塞代码,但很难找到对这些概念的简单解释。也绝对不知道console.log()
  • 最后一个问题,如果我为request 实现一个排队系统,有什么建议我应该一起批处理多少请求以及多久发送一次?
  • stackoverflow.com/a/19101225/3602796 很好地解释了请求模块在使用池模式时实际上是如何为您排队的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-27
  • 2018-08-19
  • 2015-08-31
  • 2019-02-11
  • 1970-01-01
  • 1970-01-01
  • 2018-08-26
相关资源
最近更新 更多