You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js机器人CPU占用100% 寻求不减速的优化方案

问题

近期用Node.js开发了一个机器人,CPU占用率达到100%,运行负担极大。使用了node-fetch、async.parallel和setInterval,不确定CPU满载的原因,猜测可能与setInterval队列有关。代码如下:

async.parallel({
  task1: function () {
    setInterval(function () {
      let itemRandomizer =
        config.generalInfo.itemList[
          Math.floor(Math.random() * config.generalInfo.itemList.length)
        ];
      let cookieRandomizer =
        randomCookies[Math.floor(Math.random() * randomCookies.length)];
      fetch(url, {
        method: "GET",
        agent,
        headers: {
          "Content-Type": "application/json",
          cookie: `cookie=${cookieRandomizer}`,
        },
      })
        .then((res) => res.json())
        .then((json) => {
          checks++;
          //console.log(checks, itemRandomizer, json.data[0].price)
        })
        .catch((err) => {});
    }, 0);
  },
  task2: function () {
    /* same code as task 1 (total 20 tasks) */
  },
});

不想增大执行间隔,希望保持现有速度,但100%的CPU占用实在不合理,请问有什么解决办法?setInterval是否本身就高耗CPU?另外我认为线程比async.parallel更耗CPU,所以没有使用线程。

解决办法

  • CPU满载的核心原因:你开了20个setInterval(..., 0)定时器,Node.js中setInterval的最小执行间隔受事件循环限制,不可能真的0毫秒触发,但20个定时器会疯狂把回调塞进事件循环队列。虽然每个回调里的fetch是异步的,但回调本身执行速度极快,定时器会立刻再次调度下一次执行,导致主线程被这些定时器的调度逻辑占满,直接拉满CPU。另外async.parallel在这里完全没用——它的作用是等待一组异步任务完成,但你每个task只是调用setInterval(这个函数是同步返回的),所以async.parallel瞬间就执行完,20个定时器直接同时启动,没有任何并发控制。

  • setInterval本身不耗CPU:只有当你用它无限制触发高频回调,或者回调里有同步阻塞代码时,才会导致CPU飙升。你的问题是高频+多实例的定时器调度,而非setInterval本身。

  • 具体优化方案:

    1. 删掉async.parallel和所有setInterval,改用并发控制维持请求速度。比如用p-limit库(或自己实现简单并发队列),固定同时运行的请求数量,每次请求完成后立刻发起新请求,既保持高请求频率,又不会让定时器占用CPU。
      示例思路:
      const pLimit = require('p-limit');
      const limit = pLimit(10); // 控制同时10个请求在跑,可根据实际调整
      
      // 无限循环发起请求,由p-limit控制并发
      async function runTasks() {
        while(true) {
          await limit(async () => {
            let itemRandomizer = config.generalInfo.itemList[Math.floor(Math.random() * config.generalInfo.itemList.length)];
            let cookieRandomizer = randomCookies[Math.floor(Math.random() * randomCookies.length)];
            try {
              const res = await fetch(url, {
                method: "GET",
                agent,
                headers: {
                  "Content-Type": "application/json",
                  cookie: `cookie=${cookieRandomizer}`,
                },
              });
              const json = await res.json();
              checks++;
            } catch (err) {
              // 补全错误处理,避免隐藏问题
              console.error('请求失败:', err);
            }
          });
        }
      }
      
      runTasks();
      
    2. 抛弃setInterval(0)写法:这种写法会让事件循环被定时器回调淹没,完全没必要。通过并发控制维持请求密度,比定时器高效得多。
    3. 补全错误处理:之前的空catch会隐藏请求失败的问题,比如某些请求反复失败可能导致无效CPU消耗,加上错误处理能排查潜在问题。
  • 关于线程的误解:Node.js单线程模型在IO密集型任务(比如你的网络请求)上效率很高,不需要手动开线程。你之前的问题根本不是线程问题,而是定时器滥用导致的调度过载。

内容的提问来源于stack exchange,提问作者cooldevnocap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:52:56