Node.js 并发控制

news2024/11/18 2:39:07

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它使得 JavaScript 可以脱离浏览器在服务器端运行。由于 Node.js 采用单线程异步非阻塞 I/O 模型,它的并发处理能力也是非常强大的。本文将详细介绍 Node.js 的并发原理、概念、图解、解决方案以及实际例子,并在最后进行总结。

并发原理与概念

事件循环与回调队列

Node.js 使用事件循环(Event Loop)模型来处理 I/O 操作和执行回调函数。事件循环模型中,所有任务被分为两类:同步任务和异步任务。同步任务在单个线程中执行,而异步任务则注册到回调队列中,等待事件循环处理。

非阻塞 I/O

Node.js 的 I/O 操作是非阻塞的,这意味着当一个 I/O 操作开始时,控制权会立即返回给 Node.js,允许它处理其他任务。一旦 I/O 操作完成,相应的回调函数会被放入回调队列,并在下一个事件循环迭代中执行。

并发控制图解

 

Node.js 并发解决方案 

1. 使用 Promises

Promise 是异步编程的一种解决方案,它代表了一个可能还没有完成计算的值。在 Node.js 中,你可以使用 Promise 来处理异步操作的并发。

2. async/await

async/await 是基于 Promise 的另一种编写异步代码的方式,它可以让异步代码看起来像同步代码,使得逻辑更加清晰。

3. 子线程(Worker Threads)

Node.js 10 版本开始引入了 worker_threads 模块,允许创建子线程来执行 CPU 密集型任务,从而提高并发性能。

实际例子

以下是一个使用 async/await 处理并发的简单例子:

const http = require('http');

async function fetchData(urls) {
  const results = [];

  for (const url of urls) {
    const data = await new Promise((resolve, reject) => {
      const req = http.get(url, (res) => {
        let body = '';
        res.on('data', (chunk) => body += chunk);
        res.on('end', () => resolve(body));
      });

      req.on('error', reject);
    });

    results.push(data);
  }

  return results;
}

fetchData(['http://example.com', 'http://another.com'])
  .then((results) => {
    console.log(results);
  })
  .catch((error) => {
    console.error(error);
  });

4.集群(Cluster)模块来提高并发处理能力

在 Node.js 中,cluster 模块是一个基于内置的 HTTP 服务器的简单抽象,允许你创建多个工作进程来处理客户端请求。通过使用 cluster 模块,你可以利用服务器的多核 CPU 来提高应用程序的并发处理能力。每个工作进程都是 Node.js 运行时的一个独立实例,并且它们之间不会共享任何状态。

集群模块的工作原理

cluster 模块通过创建多个工作进程来实现并行处理。每个工作进程都会监听同一个端口,但是操作系统会确保每个请求只会被一个工作进程处理。当一个请求到达时,它会根据操作系统的调度分配给一个工作进程。这样,每个工作进程可以独立地处理请求,从而提高了应用程序的并发处理能力。

使用集群模块提高并发处理能力的步骤
  1. 引入 cluster 模块: 首先,你需要在代码中引入 cluster 模块。

const cluster = require('cluster');

   2.检查是否为主进程: 接下来,你需要检查当前进程是否为主进程。如果是,那么你可以创建工作进程;如果不是,那么代码将作为工作进程运行。

if (cluster.isMaster) {
  // 主进程代码
} else {
  // 工作进程代码
}

   3. 创建工作进程: 在主进程中,你可以使用 cluster.fork() 方法来创建工作进程。每个新创建的工作进程都会自动监听服务器端口。

for (let i = 0; i < require('os').cpus().length; i++) {
  cluster.fork();
}

  4.处理工作进程消息: 你可以使用 cluster.on('online', ...) 事件来知道何时工作进程已经准备好处理请求。你还可以监听其他事件,比如 exit 事件,以便在工作进程退出时进行清理工作。

cluster.on('online', (worker) => {
  console.log(`Worker ${worker.process.pid} is online`);
});

cluster.on('exit', (worker, code, signal) => {
  console.log(`Worker ${worker.process.pid} died`);
  // 可以在这里创建新的工作进程来替代已退出的工作进程
});

   5.工作进程中的处理逻辑: 在工作进程中,你需要设置自己的 HTTP 服务器或其他服务来处理请求。这通常涉及到使用 http 模块或其他第三方模块

if (cluster.isWorker) {
  const http = require('http');
  const server = http.createServer((req, res) => {
    // 处理请求
    res.end('Hello from worker ' + cluster.worker.id);
  });

  server.listen(port, () => {
    console.log(`Worker ${cluster.worker.id} started`);
  });
}

除了使用 Node.js 的集群(Cluster)模块,还有多种方法可以提高应用程序的并发处理能力,以下是整理的相关解决方案,就不再一一举例讲解了:

  1. 使用异步编程模型10:Node.js 利用事件循环和回调函数的机制,可以在等待 I/O 操作的同时处理其他请求,从而提高系统的并发处理能力。通过使用 async/await 或 Promise 来处理异步操作,可以确保代码的简洁性和效率。

  2. 采用事件驱动的框架10:使用事件驱动的框架(如 Express 或 Koa)可以更好地管理和处理高并发的请求。这些框架提供了丰富的中间件和路由处理功能,使得开发者能够构建可扩展的应用程序。

  3. 使用缓存技术10:利用缓存技术(如 Redis)存储经常访问的数据,减少对数据库的访问次数,提高系统的响应速度和并发处理能力。缓存可以显著减少数据库的负载,从而提高整体的并发处理速度。

  4. 流式处理10:Node.js 的流式处理能力可以有效地处理大规模数据的并发处理。通过使用流(Streams),可以逐步处理数据,减少内存占用,提高系统的并发处理能力。

  5. 使用连接池10:在与数据库或其他外部服务进行交互时,使用连接池可以管理和复用连接,避免频繁地创建和销毁连接,提高系统的并发处理能力。

  6. 采用分布式架构10:将系统拆分为多个独立的服务,每个服务可以独立运行并处理自己的请求。使用分布式架构可以提高系统的可伸缩性和容错性。

  7. 使用限流和熔断机制10:通过限制请求的速率或在系统压力过大时停止接收请求,可以保护系统不被过多的请求压垮。这有助于维持系统的稳定性和可靠性。

  8. 利用多线程(Worker Threads)15:Node.js 提供了 worker_threads 模块,允许创建子线程来执行 CPU 密集型任务,从而提高并发性能。这可以充分利用多核处理器的性能。

  9. 使用进程管理工具611:工具如 PM2 提供了进程管理、负载均衡和自动重启等功能,可以帮助提高 Node.js 应用程序的稳定性和并发处理能力。

通过上述方法的组合使用,开发者可以根据具体的业务需求和系统架构来选择合适的解决方案,以提高 Node.js 应用程序的并发处理能力。

总结

      Node.js 的并发控制主要依赖于事件循环和非阻塞 I/O,通过使用 Promises、async/await 以及子线程等技术,可以有效地处理高并发场景。开发者应根据实际需求选择合适的并发解决方案,以提高应用程序的性能和响应速度。随着 Node.js 的不断发展,未来可能会出现更多高效的并发处理方案。

扩展:使用 cluster 模块可以显著提高 Node.js 应用程序的并发处理能力,特别是在多核 CPU 服务器上。通过创建多个工作进程,你可以让每个核心都参与到请求处理中,从而提高整体的处理速度和效率。然而,需要注意的是,cluster 模块并不适用于所有场景,特别是对于 I/O 密集型应用,它的效益可能不如使用异步 I/O 和事件循环模型。在使用 cluster 模块时,还需要考虑到进程间通信和状态共享的问题,因为每个工作进程都是独立的。

 

整理分享不易,如果对客官有帮助还请点点赞!下一篇介绍node中的rsa加密

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1594731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

洛谷-P2089 烤鸡

P2089 烤鸡 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<bits/stdc.h> using namespace std; const int N30; //const int M1e3*310; const int Mpow(3,10); int n; int arr[N]; //存临时方案 int res; //存方案数 int ans[M][N]; //存所有方案//x表示当前到…

k8s:kubectl 命令设置简写启用自动补全功能

k8s&#xff1a;kubectl 命令设置简写&启用自动补全功能 1、设置kubectl命令简写2、启用kubectl自动补全功能 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Kubernetes&#xff08;K8s&#xff09;是一个强大的容器编排平台&#xff0…

LangChain安装

安装步骤 1 安装Python环境 这里不介绍Python环境的配置&#xff0c;默认大家是已经安装并配置好Python运行环境的。 2 安装LangChain bash 复制代码 pip install langchain执行以上命令安装LangChain会默认安装LangChain的最新版本 3 测试安装结果 3.1 打印langchain版本…

如何获得easyrecovery软件密钥?2024最新学习步骤教程

如何获得easy recovery密钥&#xff1f;EasyRecovery是一款老牌的数据恢复软件&#xff0c;如果需要使用它来恢复数据&#xff0c;则需要购买密钥激活。然而&#xff0c;如果您只需要使用它一两次而不想花钱购买密钥&#xff0c;那么您可以使用免费的EasyRecovery密钥。请注意&…

贝乐虎儿歌v6.8.0解锁高级版亲子学习儿歌

软件介绍 贝乐虎儿歌免费版app&#xff0c;出自乐擎网络的创意工坊&#xff0c;专为孩子们雕琢了一系列富含创意的动画儿歌内容。这款app通过贝乐虎兄弟的可爱形象&#xff0c;让孩子们在愉快的观看中接触到各种儿歌和故事。不仅如此&#xff0c;app还巧妙地将古诗、英语等学习…

Java代码基础算法练习-求奇数和-2024.04.14

任务描述&#xff1a; 输入n个整数&#xff08;n从键盘输入&#xff0c;n>0&#xff0c;整数取值范围&#xff1a;0~1000&#xff09;&#xff0c;输出它们的奇数和。 任务要求&#xff1a; 代码示例&#xff1a; package April_2024;import java.util.Scanner;// 输入n个…

【Leetcode】1702. 修改后的最大二进制字符串

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 给你一个二进制字符串 b i n a r y binary binary &#xff0c;它仅有 0 0 0 或者 1 1 1 组成。你可以使用下面的操作任意次对它进行修改&#xff1a; 操作 1 &#xff1a;如果…

Nacos 入门篇---服务端如何处理客户端的服务注册请求?(三)

一、引言 ok呀&#xff0c;上个章节我们讲了Nacos客户端的服务自动注册&#xff0c;今天我们来看看服务端接收到了客户端的服务注册请求&#xff0c;服务端都做了哪些事情&#xff5e; 二、目录 目录 一、引言 二、目录 三、回顾上节内容&#xff1a; 四、Nacos 服务代码入…

Linux 网络排查命令

端口相关服务检查 netstat -ntpl|grep [$Port]说明&#xff1a;[$Port]为相应的端口号。 0.0.0.0代表本机上可用的任意地址。比如&#xff0c;0.0.0.0:80表示本机上所有地址的80端口。 tcp 0.0.0.0:80表示在所有的可用接口上监听TCP的80端口 如果返回结果为空&#xff0c;说明…

Java 入门教程||Java 关键字

Java 关键字 Java教程 - Java关键字 Java中的关键字完整列表 关键词是其含义由编程语言定义的词。 Java关键字和保留字&#xff1a; abstract class extends implements null strictfp true assert const false import package super try …

奥尔波特、卡特尔、大五人格的特质流派,预测你是内向还是外向

了解特质&#xff0c;可以预测人的行为&#xff0c;可以预测你的性格是内向还是外向。 特质论并不把人格分为绝对的类型&#xff0c;通常认为存在一些特质维度。人们之间的差异&#xff0c;就在于这些维度上表现程度的不同所形成的不同特质构型。 特质&#xff08;trait&…

Python数据结构与算法——算法(贪心算法、动态规划

贪心算法 介绍&#xff1a;贪心算法又称贪婪算法&#xff0c;是指在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;它所做出的是在某种意义上的局部最优解。 贪心算法并不保证会得到最优解&#xff0c;但…

发誓不在黄金周旅游,可惜管不住自己,看看景区可视化,觉悟了。

2023-10-04 23:29贝格前端工场 景区可视化大屏可以起到以下几个作用&#xff1a; 数据监控和分析&#xff1a;景区可视化大屏可以实时监控景区的各项数据指标&#xff0c;如游客数量、门票销售情况、景区设备运行状态等&#xff0c;通过可视化展示&#xff0c;管理人员可以快…

C/C++基础----指针

指针的定义 在c/c中&#xff0c;有一个特殊的变量指向我们电脑中某个内存地址&#xff0c;进而可以让我们操作这段内存&#xff0c;指的就是指针类型 语法&#xff1a; int a 10; int* p &a;&符号是取出某个变量的内存地址 把这个内存地址赋值给一个变量p&#xff…

分享一个 git stash 的实际使用场景。

当我将新的变更记录提交为 git commit --amend 后&#xff0c;发现这需要修改云端上的提交记录&#xff0c;也就是 vscode 中会出现这张图 于是&#xff0c;我通过 git reset head^ 撤销掉刚刚的提交。 reset 前&#xff1a; reset 后&#xff1a; 但在撤销的同时&#xf…

华院计算参编《金融业人工智能平台技术要求》标准

随着人工智能技术的迅猛发展&#xff0c;金融机构正在从业务场景化向企业智能化演进&#xff0c;金融业对智能化的需求愈加迫切。为引导产业有序发展、规范行业自律、加快金融行业智能化转型&#xff0c;中国信通院依托中国人工智能产业发展联盟&#xff08;AIIA&#xff09;及…

机器学习 | 使用Scikit-Learn实现分层抽样

在本文中&#xff0c;我们将学习如何使用Scikit-Learn实现分层抽样。 什么是分层抽样&#xff1f; 分层抽样是一种抽样方法&#xff0c;首先将总体的单位按某种特征分为若干次级总体&#xff08;层&#xff09;&#xff0c;然后再从每一层内进行单纯随机抽样&#xff0c;组成…

第19讲:自定义类型:结构体

1.结构体类型的声明 2.结构体变量的创建和初始化 3.结构体变量的赋值 4.结构体成员访问操作符 5.结构体内存对齐 1.结构体类型的声明 1.1结构体声明 struct 结构体名称 { 结构体成员... } 举例&#xff1a;描述一个学生&#xff1a; 2结构体变量的创建和初始化 2.1匿…

Linux文本编辑器vim使用和分析—2

目录 1.对vim的简单理解&#xff1a; 2.看待vim的视角&#xff1a; 3.命令模式&#xff1a; 3.1vim被打开后默认的模式&#xff1a; 3.2命令模式切换插入模式&#xff1a; 3.3其他模式回到命令模式&#xff1a; 3.4光标定位&#xff1a; 4.插入模式(编辑模式)&#xff1…

数字乡村创新实践探索农业现代化与农村治理现代化新路径:科技赋能农村全面振兴与农民幸福生活

目录 引言 一、数字乡村与农业现代化 1、智慧农业技术的应用 2、农业产业链的数字化转型 二、数字乡村与农村治理现代化 1、农村信息化水平的提升 2、农村治理模式的创新 三、科技赋能农村全面振兴与农民幸福生活 1、提升农业生产效益与农民收入 2、促进农村产业结构…