百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>JS教程> node.js“多线程”怎样处置高并发任务?
分享文章到:

node.js“多线程”怎样处置高并发任务?

发布时间:01/01 来源:未知 浏览: 关键词:
下面本篇文章给大家介绍一下使用 nodejs “多线程”处置高并发任务的办法。有必然的参照 价值,有需要的伴侣可以参照 一下,但愿对大家有所帮忙。

相关引荐:《nodejs视频教程》

摩尔定律

摩尔定律是由英特尔结合开创人戈登·摩尔(Gordon Moore)在 1965 年提出的,即集成电路上可容纳的元器件的数目每隔 18 至 24 个月就会增添一倍,机能也将晋升一倍。也就是说,处置器(CPU)的机能每隔大约两年就会翻一倍。

间隔摩尔定律被提出到此刻,已经过去了 50 多年。如今,随着芯片组件的规模越来越接近单个原子的规模,要跟上摩尔定律的步调变得越来越艰难。

在 2019 年,英伟达 CEO 黄仁勋在 ECS 展会上说:“摩尔定律过去是每 5 年增长 10 倍,每 10 年增长 100 倍。而如今,摩尔定律每年只能增长几个百分点,每 10 年大概只要 2 倍。因此,摩尔定律完毕了。”

单个处置器(CPU)的机能越来越接近瓶颈,想要冲破这个瓶颈,则需要充分利用 多线程技术,让单个或多个 CPU 可以同时施行多个线程,更快的完成运算机任务。

Node 的多线程

我们都知道,Javascript 是单线程说话,Nodejs 利用 Javascript 的特性,使用事件驱动模型,实现了异步 I/O,而异步 I/O 的背后就是多线程调度。

Node 异步 I/O 的实现可以参照 朴灵的 《深入浅出 Node.js》

Go 说话中,可以通过创立 Goroutine 来显式调取一条新线程,并且通过环境变量 GOMAXPROCS 来操纵最大并发数。

Node 中,没有 API 可以显式创立新线程的 ,Node 实现了一些异步 I/O 的 API,例如 fs.readFilehttp.request。这些异步 I/O 底层是调取了新线程施行异步任务,再利用事件驱动的模式来猎取施行结果。

效劳端开发、工具开发大概都会需要使用到多线程开发。比方使用多线程处置复杂的爬虫任务,用多线程来处置并发恳求,使用多线程停止文件处置等等...

在我们使用多线程时,必然要操纵最大同时并发数。由于不操纵最大并发数,大概会致使 文件描写符 耗尽激发的错误,带宽不足激发的网络错误、端口限制激发的错误等等。

Node 中并没有用于操纵最大并发数的 API 或者环境变量,所以接下来,我们就用几行简便的代码来实现。

代码实现

我们先假设下面的一个需求场景,我有一个爬虫,需要每天爬取 100 篇掘金的文章,假如一篇一篇爬取的话太慢,一次爬取 100 篇会由于网络连接数太多,致使许多恳求直接失败。

那我们可以来实现一下,每次恳求 10 篇,分 10 次完成。这样不仅可以把效力晋升 10 倍,并且可以不乱运转。

下面来看看单个恳求任务,代码实现如下:

const axios = require("axios");

async function singleRequest(article_id) {
  // 这里我们直接使用 axios 库停止恳求
  const reply = await axios.post(
    "https://api.juejin.cn/content_api/v1/article/detail",
    {
      article_id,
    }
  );

  return reply.data;
}

为了利便演示,这里我们 100 次恳求的都是统一个地址,我们来创立 100 个恳求任务,代码实现如下:

// 恳求任务列表
const requestFnList = new Array(100)
  .fill("6909002738705629198")
  .map((id) => () => singleRequest(id));

接下来,我们来实现并发恳求的办法。这个办法支撑同时施行多个异步任务,并且可以限制最大并发数。在任务池的一个任务施行完成后,新的异步任务会被推入连续施行,以包管任务池的高利用率。代码实现如下:

const chalk = require("chalk");
const { log } = require("console");

/**
 * 施行多个异步任务
 * @param {*} fnList 任务列表
 * @param {*} max 最大并发数限制
 * @param {*} taskName 任务名称
 */
async function concurrentRun(fnList = [], max = 5, taskName = "未命名") {
  if (!fnList.length) return;

  log(chalk.blue(`开端施行多个异步任务,最大并发数: ${max}`));
  const replyList = []; // 收集任务施行结果
  const count = fnList.length; // 总任务数目
  const startTime = new Date().getTime(); // 记载任务施行开端时间

  let current = 0;
  // 任务施行程序
  const schedule = async (index) => {
    return new Promise(async (resolve) => {
      const fn = fnList[index];
      if (!fn) return resolve();

      // 施行当前异步任务
      const reply = await fn();
      replyList[index] = reply;
      log(`${taskName} 事务进度 ${((++current / count) * 100).toFixed(2)}% `);

      // 施行完当前任务后,连续施行任务池的剩余任务
      await schedule(index + max);
      resolve();
    });
  };

  // 任务池施行程序
  const scheduleList = new Array(max)
    .fill(0)
    .map((_, index) => schedule(index));
  // 使用 Promise.all 大量施行
  const r = await Promise.all(scheduleList);

  const cost = (new Date().getTime() - startTime) / 1000;
  log(chalk.green(`施行完成,最大并发数: ${max},耗时:${cost}s`));
  return replyList;
}

从上面的代码可以看出,使用 Node 停止并发恳求的关键就是 Promise.allPromise.all 可以同时施行多个异步任务。

在上面的代码中,创立了一个长度为 max 最大并发数长度的数组,数组里放了对应数目的异步任务。然后使用 Promise.all 同时施行这些异步任务,当单个异步任务施行完成时,会在任务池取出一个新的异步任务连续施行,完成了效力最大化。

接下来,我们用下面这段代码停止施行测试(代码实现如下)

(async () => {
  const requestFnList = new Array(100)
    .fill("6909002738705629198")
    .map((id) => () => singleRequest(id));

  const reply = await concurrentRun(requestFnList, 10, "恳求掘金文章");
})();

终究施行结果如下图所示:

1.jpg

到这里,我们的并发恳求就完成啦!接下来我们离别来测试一下不一样并发的速度吧~ 第一是 1 个并发,也就是没有并发(如下图)

2.jpg

耗时 11.462 秒!当不使用并发时,任务耗时非常长,接下来我们看看在其他并发数的状况下耗时(如下图)

3.jpg

4.jpg

5.jpg

6.jpg

从上图可以看出,随着我们并发数的提高,任务施行速度越来越快!这就是高并发的优势,可以在某些状况下晋升数倍乃至数十倍的效力!

我们细心看看上面的耗时会发明,随着并发数的增添,耗时还是会有一个阈值,不克不及完全呈倍数增添。这是由于 Node 实际上并没有为每一个任务开一个线程停止处置,而只是为异步 I/O 任务开启了新的线程。所以,Node 比力适合处置 I/O 密集型任务,并不适合 CPU(运算)密集型任务。

到这里,我们的使用 Node “多线程”处置高并发任务就介绍完了。假如想要程序完美一点的话,还需要思考到任务超不时间、容错机制,大家感乐趣的可以本人实现一下。

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有150人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板