亚马逊EC2上Node.js的CPU利用率

24

考虑到Node.js是单线程运行的,如果我在一个有4个EC2计算单元的Amazon EC2实例上运行Node服务器,它是否会比我只有2个EC2计算单元时运行更快/处理更多负载?

在亚马逊上,CPU利用率是否需要程序支持多线程才能充分利用所有资源?


1
我相信这就是你要找的:https://dev59.com/0XE95IYBdhLWcg3wQ7qc - Cymen
6个回答

20
为了充分利用N个核心的计算资源,您需要至少准备N个线程来执行有用的工作。这与EC2无关,这只是计算机的工作方式。我假设从您的问题中可以看出,您正在选择m1.medium和m1.large实例类型,它们分别具有1个和2个专用核心(m1.small是半个共享核心,而m1.xlarge是完整的4核心专用盒子)。因此,您需要至少两个进程执行有用的工作才能使用更大的盒子(除非您只想访问更多的内存/IO)。
每个Node.js进程都是按设计单线程的。这使它提供了一种不受锁定语义限制的清洁编程范例。这很大程度上是按设计完成的。
对于Node.js应用程序要利用多个核心,它必须生成多个进程。然后,这些进程将使用某种形式的消息传递(管道、套接字等)进行通信——与“共享内存”相反,在其中代码可以直接改变可见于多个进程的内存位置,这需要锁定语义。
实际上,这很简单易于设置。在Node.JS v0.6.X中,“cluster”模块已经集成到标准发行版中,因此可以轻松设置多个节点工作程序来监听单个端口。请注意,此“cluster”模块与learnboost的“cluster”模块不同,具有不同的API并拥有NPMjs注册表中的“cluster”名称。

http://nodejs.org/docs/latest/api/cluster.html

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  http.Server(function(req, res) { ... }).listen(8000);
}

1
这可能还没有达到“答案”状态,但它非常有帮助。感谢您发布它。我本来要放弃node.js开发的,但现在你又让我对它感兴趣了。 - Geek Stocks
1
在某些情况下,我认为像pm2中的集群模式比自己分叉进程更好。如果您正在构建具有多个工作进程的服务器,请务必立即查看pm2 - Will Brickner

17

回答你的问题,如果你只写“标准”的单线程JavaScript代码(你会受限于一个CPU),那么增加更多内核以提高节点性能是不起作用的。

这是因为node.js使用事件循环进行处理,所以如果你只启动一个单独的node.js进程而没有其他任何操作,它将不是多线程的,因此不会使用多个CPU(核心)。

然而,您可以使用node.js集群API来分叉(node process)进程,以便利用多个CPU(核心): https://nodejs.org/docs/latest/api/cluster.html。如果你以这种方式编写你的代码,那么拥有更多的计算单元将有助于你。

有一个注意事项,就是EC2计算单元是按每个实例详细说明的:http://aws.amazon.com/ec2/instance-types/。对于某些实例,你可以获得更多的“计算单元”每个虚拟核心。因此,如果你选择一个每个虚拟核心具有 2个计算单元的实例,而不是一个每个核心只有一个计算单元的实例,则你将能够在具有更多计算单元的CPU上执行node。然而,看起来在2个计算单元之后,计算功率会按核心分割,这意味着你不会从多个内核中获得任何好处。


6

亚马逊针对实例类型的总“EC2计算单元”概念并不直接映射到CPU或核心。它是每个核心在EC2计算单元(它们自己的相对度量)中的速度乘以核心数量。

亚马逊确实列出了每个实例类型有多少虚拟核心:

http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?instance-types.html

你最好的选择是使用所有的核心,正如其他人所指出的。然而,如果你最终采用单线程解决方案,那么你将需要关注各个核心的速度,而不是所有核心的总EC2计算单位。

3
在Node.js中,你的代码是单线程的,但访问文件系统或数据库服务器等调用不使用主Node.js线程。主线程在等待4GB从磁盘读取到内存或等待DB服务器返回响应时仍然保持执行。一旦操作完成,提供的回调将被放入队列以在主线程中执行。总之,就是这样。
优点是,在服务器情况下,您拥有一个非常快速的线程,可以处理数千个并发请求,而不会完全阻塞任何一个请求或为每个客户端请求-响应周期生成一个操作系统线程。
更重要的是,您应该在EC2上针对您特定的用例进行基准测试 - 如果应用程序执行大量IO,则在运行单个Node实例时使用多个处理器可能很有用。

2
如果我在亚马逊EC2实例上运行一个具有4个EC2计算单元的节点服务器,它能比使用2个EC2计算单元时运行得更快/处理更多负载吗?
不会的,如果您将node.js用作服务器,则只能访问单个核心。
var http = require('http');
    http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

生成单个监听器,并不意味着只有一个连接。Node.js打破了传统的思维方式。除非你编写不当,事件循环不会阻止连接。了解事件循环的重要性,请参考此篇文章。我花了一段时间才真正理解其含义。

在亚马逊上,需要程序支持多线程才能充分利用所有资源吗?

是的,经过正确配置的apache/nginx将利用多CPU配置。正在开发可以利用这些配置的node.js服务器,详情请参见此处

0

针对那些提出好观点的人,关于现代 Node.JS 的功能(旧帖子在这里),除了Node实现在V8和LibUV之上,并利用内部线程池外,你的JS代码实际上可以是多线程的。不仅仅是使用thread_workers API。很可能一些依赖项使用了C++ / V8 / NAPI绑定的JS并直接使用底层线程池。

例如: 您会发现npm上的标准bcrypt库是使用C ++中的多线程实现其blowfish实用程序。许多人没有正确阅读文档,因此对其他工作线程中库里的加密工作没有加速感到困惑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接