Nodejs在cpu核心数超过六个时 cpu利用率就变得特别低了

Nodejs在cpu核心数超过六个时 cpu利用率就变得特别低了

服务器是4个8线程的cpu,总共有32个计算核心

但node.js只在暂用6核心的时候 能发挥最大性能 每个计算核心大概能到90% rps能跑到1.4w

超过6个cluster的时候,再怎么加cluster, rps都跑不高了(反而会降下来)

而且这时候每个cpu核心的利用率也会变得特别低,大概只能到30% -40%

大家有碰到过类似的情况么?

8 回复

Nodejs在CPU核心数超过六个时 CPU利用率就变得特别低了

背景介绍

我最近在一个服务器上运行了一个Node.js应用,该服务器配置为四个八线程的CPU,总共拥有32个计算核心。在使用Node.js进行多进程处理时,我发现当Node.js进程占用6个核心时,应用可以达到最佳性能,每个计算核心的RPS(Requests Per Second)大约能达到1.4万。

然而,当我尝试增加更多的Node.js子进程以利用更多核心时,RPS并没有如预期那样提高,反而开始下降。同时,每个核心的CPU利用率也显著降低,只有30%-40%左右。

可能的原因

这种现象可能与Node.js的事件循环机制有关。Node.js默认采用单线程模型,即使在使用cluster模块创建多个子进程时,每个子进程仍然依赖于单线程事件循环来处理请求。因此,当核心数量过多时,可能会导致线程之间的竞争加剧,从而影响整体性能。

示例代码

以下是一个简单的Node.js代码示例,展示如何使用cluster模块来创建多个子进程:

const cluster = require('cluster');
const os = require('os');

if (cluster.isMaster) {
    console.log(`Master process running on ${process.pid}`);

    // 计算可用的核心数
    const numCPUs = os.cpus().length;

    // 创建指定数量的子进程
    for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    // 监听子进程退出事件
    cluster.on('exit', (worker, code, signal) => {
        console.log(`Worker ${worker.process.pid} died`);
    });
} else {
    console.log(`Worker process running on ${process.pid}`);
    
    // 处理具体的业务逻辑
    setInterval(() => {
        // 业务逻辑
    }, 1000);
}

解决方案

  1. 调整核心分配:限制Node.js子进程的数量,使其不超过实际需要的核心数。
  2. 优化事件循环:确保业务逻辑中没有阻塞事件循环的操作,例如长时间的I/O操作或复杂的计算。
  3. 使用多线程库:考虑使用支持多线程的库,如worker_threads,来更有效地利用多核处理器。

通过这些方法,你可以更好地利用多核处理器的优势,提升Node.js应用的整体性能。


在下小白一枚,Node.js不是据说是单线程么?一直都想知道如何多核运行,求教。

4个8线程的cpu 还是四核8线程?

我测试过,貌似效果都不如你这个,我当时好像因为网络传输的问题,效率一直上不去,不知道你这样的结果,网络传输速度是多少,贴出看看吧

兄弟,楼主的算的是对的,cluster用的确实是核心数

node版本多少?

好高深,求科普

Node.js 在 CPU 核心数超过一定数量时,CPU 利用率降低的现象通常是由于线程管理和上下文切换开销增加导致的。Node.js 是单线程事件循环模型,尽管可以使用 cluster 模块来创建多个进程,但每个进程内部仍然主要由一个事件循环处理。当 CPU 核心数过多时,进程间通信和上下文切换会导致额外的开销。

示例代码

假设我们有以下 Node.js 应用,使用 cluster 模块创建多个子进程:

const os = require('os');
const cluster = require('cluster');

if (cluster.isMaster) {
    const numCPUs = os.cpus().length;
    console.log(`Master process running on ${numCPUs} cores`);

    for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('exit', (worker, code, signal) => {
        console.log(`Worker ${worker.process.pid} died`);
    });
} else {
    // 子进程的业务逻辑
    const http = require('http');
    http.createServer((req, res) => {
        res.writeHead(200);
        res.end('Hello World\n');
    }).listen(8000);

    console.log(`Worker ${process.pid} is running`);
}

解释

  1. 单线程限制:Node.js 的事件循环模型是单线程的,这意味着即使你创建了多个进程,每个进程内部仍然只有一个线程处理请求。
  2. 进程间通信开销:多进程模式下,进程间的通信需要额外的时间和资源。
  3. 上下文切换:当进程数量过多时,操作系统频繁进行进程间的上下文切换,这会增加系统开销。
  4. 负载均衡:如果负载均衡做得不好,部分进程可能承担过多的请求,而其他进程则空闲,导致资源浪费。

解决方案

  1. 调整进程数:尝试将进程数设置为合理的核心数(如 6-8),而不是所有可用核心数。
  2. 优化负载均衡:确保请求均匀地分布在各个进程中。
  3. 使用 Worker Threads:Node.js 10.5.0 引入了 worker_threads 模块,可以在单个进程中利用多核 CPU,减少进程间通信的开销。
const { Worker } = require('worker_threads');

if (require.main === module) {
    const numWorkers = Math.min(os.cpus().length, 8); // 设置合理的进程数
    for (let i = 0; i < numWorkers; i++) {
        new Worker(__filename);
    }
} else {
    const http = require('http');
    http.createServer((req, res) => {
        res.writeHead(200);
        res.end('Hello World\n');
    }).listen(8000);
}

通过这些方法,你可以更好地利用多核 CPU 并提高应用性能。

回到顶部