题目:Top 5 Node.js Features Every Developer Should Know
作者:Danusha Navod
链接:https://blog.bitsrc.io/top-5-features-of-nodejs-e49d1c68f4a7
无论你是经验丰富的 Node.js 开发人员还是老成持重的新人开发者,总有一些货色在 Node.js 中期待着咱们去摸索。
在本文中,我将探讨能够加强整体体验的五个 Node.js 性能,它们是:
- Worker Threads
- Cluster Process Module
- Built-in HTTP/2 Support
- Streams API
- REPL
让咱们逐个探讨这些性能中的每一个。
但在此之前,让咱们疾速看一下 Node.js 的 单线程行为。理解这个基本知识将为咱们将要深入研究的性能提供有价值的背景信息。
单线程 Node.js:疾速概述
Node.js 以其单线程架构而闻名。但更精确地说,称其为“单线程事件循环”。
但为什么要应用单线程事件循环呢?
最后,Node.js 是为 I/O 绑定工作(如 Web 服务器)设计的。对于这些,创立多个线程会减少治理线程同步和上下文切换的开销和复杂性。相同,Node.js 采纳了事件驱动的办法。
这种行为给 Node.js 带来了一些长处和局限性。
长处还能够,然而局限性呢?
Node.js 单线程事件循环带来的次要限度如下:
- 受 CPU 限度的工作可能会阻塞循环: 大量的计算可能会“解冻”循环,从而影响对其余申请的响应能力。
- 没有真正的并行性: 工作依然一个接一个地执行,而不是同时执行。
为了解决这些限度,Node.js 引入了各种 Node.js 版本的工作 线程 和集群模块。
这两个性能能够真正影响咱们的软件开发之旅。因而,让咱们在接下来的局部中深入研究 工作者线程 Worker Threads 和集群模块 Cluster Module,以理解它们令人难以置信的有用性。
之后,咱们将摸索 另外三个 Node.js 性能,它们能够在各种状况下提供帮忙。敬请关注!
1. Worker Threads 工作者线程
<img src=”https://fs.lwmc.net/uploads/2024/02/1708076388928-202402161739358.webp” alt=”0*uHcdivbqfc5PwBei” style=”zoom:50%;” />
尽管单线程事件循环善于解决 I/O 密集型工作,但 Node.js 的 worker_threads
模块使你可能在解决 CPU 密集型 时解脱其限度运行。
设想一下,多个厨师在厨房里独立工作,同时筹备不同的菜肴(工作)——这就是工作者线程的实质!
幕后产生了什么?
默认状况下,Node.js 具备单线程事件循环,善于解决 I/O 密集型工作。但对于 CPU 密集型工作来说,它可能会成为瓶颈。
将工作线程视为同一 Node.js 过程中独自的 JavaScript 执行上下文。
它能够将 CPU 密集型工作委托给这些工作线程,而不是由主线程解决所有事件。这容许主线程放弃响应并解决其余申请,同时工作者线程解决简单的计算。
实质上,工作者线程容许:
- 卸载 CPU 密集型工作: 开释主线程以进行其余工作。
- 实现并行性:并发执行工作以取得更快的性能。
- 高效共享数据:防止在过程之间复制数据的开销。
工作者线程入门
worker_threads
模块提供了一个简略的 API 用于创立工作线程并与其通信:
const {Worker} = require('worker_threads');
const worker = new Worker('./worker.js', { data: { someData: 'to process'} });
worker.on('message', (message) => {console.log(Received message from worker: ${message} );
});
worker.postMessage({anotherData: 'to send'});
请记住,工作者线程共享内存。因而,倡议进行大型数据交换时应用 ArrayBuffer
或 SharedArrayBuffer
等数据结构,以防止不必要的复制。
还请记住:
- 创立和管理工作线程会产生一些开销,因而请依据你的特定用例思考其收益与老本。
- 线程平安至关重要!应用同步机制来确保数据完整性。
- 工作者线程会减少复杂性,因而请明智地应用它们来执行真正受害于并行性的工作。
2. Cluster Process Module 集群过程模块
<img src=”https://fs.lwmc.net/uploads/2024/02/1708077038739-202402161750378.webp” alt=”0*4F2f1LHzjAJE8pDf” style=”zoom: 67%;” />
尽管工作者线程非常适合并行性,但集群模块使你可能在多核零碎中走得更远。
设想一下,有多个厨房(Node.js 过程)独立运行,每个厨房同时解决申请 – 这就是集群的力量!
幕后产生了什么?
集群模块 创立多个独立的 Node.js 过程,每个过程都有本人的事件循环和内存空间。
这些过程在 不同的内核 上独立运行,利用多个内核来进步性能( 程度扩大 )
这是通过创立一个主过程和多个工作过程来操作的。主过程管理工作过程之间传入连贯的调配。如果工作过程产生故障,主过程能够从新生成一个新过程,从而确保在产生故障时的稳健性。
但为什么要拥抱集群呢?
- 晋升性能:解决更高的流量并缩短响应工夫,尤其是对于 I/O 密集型工作。
- 最大限度地进步资源利用率:充分利用服务器中的所有可用内核,显着进步解决能力。
- 加强的容错能力:如果一个 Worker 解体,其余 Worker 会放弃利用程序运行,从而确保可靠性和失常运行工夫。
集群入门
cluster
模块提供了一个简略的 API 用于设置和管理工作过程:
const cluster = require('cluster');
if (cluster.isMaster) {
// Master process
const numWorkers = require('os').cpus().length;
for (let i = 0; i < numWorkers; i++) {cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {console.log(worker ${worker.process.pid} died );
});
} else {
// Worker process
// Your application logic here
app.listen(3000);
}
记住:
- Worker 过程共享内存和资源,所以要认真思考数据同步。
- 集群模块减少了应用程序架构的复杂性,因而请依据你的特定需要评估其劣势与复杂性。
何时思考应用集群:
- 高流量网站:当单线程事件循环达到极限时,通过集群程度扩大有助于无效治理大型用户群。
- 长时间运行的工作:如果某些申请波及简短的操作(例如图像处理或数据加密),则将它们散布在工作过程之间能够进步对其余申请的响应能力。
- 容错至关重要:对于要害工作应用程序,集群模块对单个过程故障的恢复能力提供了贵重的爱护。
3. 内置 HTTP/ 2 反对
<img src=”https://fs.lwmc.net/uploads/2024/02/1708143321433-202402171215881.webp” alt=”0*4LhdUVLCf5JMGLr_” style=”zoom:50%;” />
尽管工作者线程和集群模块解决了不同的问题,但 Node.js 的 http2
模块通过为高效的 HTTP/2 协定 提供内置反对来间接解决性能问题。
什么是 HTTP/2?
HTTP/2 是 HTTP/1.1 的后继者,带来了多项性能加强:
- 多路复用:容许在单个连贯上同时发送和接管多个申请和响应,打消困扰 HTTP/1.1 的队头阻塞问题。
- header 压缩: 通过压缩 header 来放大标头大小,从而显着缩小数据传输开销。
- 服务器推送 Server push:容许服务器在客户端申请资源之前被动将资源发送给客户端,从而可能放慢页面加载工夫。
Node.js 如何反对 HTTP/2?
Node.js 提供了一个弱小的 http2
模块来应用 HTTP/2。以下是它提供的一些性能:
- 创立 HTTP/2 服务器: 应用相熟的 Node.js 服务器模式以及用于治理流和服务器推送性能的附加选项。
- HTTP/2 客户端 : 拜访客户端性能以连贯到 HTTP/2 服务器并与之交互。
- Extensive API: 摸索各种办法和事件来治理连贯、流、推送机制和错误处理。
http2 入门
Node.js 文档 提供了应用 http2 模块的具体指南和示例。然而,仅仅提供链接是不够的。让咱们通过一些理论示例来演示其用法。
1. 创立一个根本的 HTTP/2 服务器:
const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream, headers) => {
stream.respond({
'status': 200,
'content-type': 'text/plain',
});
stream.end('Hello from your HTTP/2 server!');
});
server.listen(3000, () => {console.log('Server listening on port 3000');
});
此代码创立一个简略的服务器,向通过 HTTP/2 连贯的任何客户端发送“Hello”音讯。
2. 解决客户申请:
const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream, headers) => {const path = headers[':path'];
if (path === '/') {
stream.respond({
'status': 200,
'content-type': 'text/plain',
});
stream.end('Hello from HTTP/2 server!');
} else {
stream.respond({
'status': 404,
'content-type': 'text/plain',
});
stream.end('Not found');
}
});
server.listen(3000, () => {console.log('Server listening on port 3000');
});
此代码扩大了后面的示例以解决不同的申请门路 (/) 并发送适当的响应。
4. Streams API
<img src=”https://fs.lwmc.net/uploads/2024/02/1708156649905-202402171557076.webp” alt=”0*EmBQH-2R-H_F0yJo” style=”zoom:50%;” />
Node.js 的 Streams API 为应用程序中的高效数据处理提供了弱小的根底。理解流能够帮忙咱们构建可扩大且高性能的零碎。
什么是流?
设想一下数据像水流一样流动——这就是实质上的概念。
流示意随工夫传送的间断数据块序列。Node.js 提供各种流类型,每种流类型适宜不同的用例:
- 可读流:收回数据块以供应用,非常适合读取文件、网络连接或用户输出。
- 可写流:容许写入数据块,非常适合写入文件、网络连接或数据库。
- 双工流:联合读取和写入性能,对于套接字或管道等双向通信很有用。
- 转换流:在数据流经时批改数据,从而实现加密、压缩或数据操作。
为什么应该应用流 Streams?
流在波及大数据集或间断数据流的场景中表现出色。它们具备以下几个长处:
- 内存效率:它们以块的模式解决数据,防止一次性将整个数据集加载到内存中。
- 非阻塞性质:它们不会阻塞主线程,容许你的应用程序在解决数据时放弃响应。
- 灵活性:不同的流类型能够满足不同的数据处理需要。
Streams 入门
咱们来通过内置的fs
模块进行摸索。上面是一个逐块读取文件的示例:
const fs = require('fs');
const readableStream = fs.createReadStream('large_file.txt');
readableStream.on('data', (chunk) => {console.log('Received data chunk:', chunk.toString());
});
readableStream.on('end', () => {console.log('Finished reading file');
});
此代码按块读取 large_file.txt
文件并将其记录到控制台。你能够通过摸索 Node.js 文档 理解更多类型及其用法。
5. REPL (Read-Eval-Print Loop)
<img src=”https://fs.lwmc.net/uploads/2024/02/1708156971290-202402171602962.webp” alt=”0*Ti2y12Xw0U00RMg9″ style=”zoom: 67%;” />
工作者线程和集群模块有助于进步性能和可扩展性,而 HTTP/2 和流的动静组合扩大了它们的能力,提供跨多个域的多功能劣势。另一方面,REPL(读取 - 评估 - 打印循环) 引入了一种独特的性能 – 交互性和摸索。
设想一个沙箱环境,你能够在其中试验代码片段、测试想法并取得即时反馈——这就是 REPL 的实质。
将其视为 对话式编码体验。你输出代码表达式,REPL 会对其进行计算并显示后果,从而使你可能疾速迭代和学习。这使得 REPL 对于以下方面是无价的:
- 学习和试验:在平安、隔离的环境中尝试新的 JavaScript 性能、摸索库并测试假如。
- 调试和故障排除:逐行隔离并修复代码中的问题,在每一步查看变量和值。
- 交互式开发:疾速构建想法原型,立刻取得反馈,并迭代地欠缺你的代码。
拜访 REPL:
关上你的终端并简略地输出 node。瞧!你当初已进入 REPL,能够开始玩了。键入任何 JavaScript 变量赋值、函数调用,甚至简单的计算。
Welcome to Node.js v20.11.0.
Type ".help" for more information.
> Math.random()
0.6148448277159013
与后面概述的所有弱小性能相比,REPL 可能看起来非常简单。然而,它的真正价值只有通过实践经验能力显现出来。作为一名 Node.js 开发人员,采纳 REPL 并将其集成到你的工作流程中不仅无益,而且至关重要。
结论性思考
在 Node.js 提供的弱小工具库中,工作者线程 负责解决 CPU 密集型工作,集群模块 反对程度扩大,http2赋予 HTTP/2 网络协议的能力,Streams 提供高效的数据处理,REPL 反对交互式摸索和学习。
通过了解与把握这些性能,将开释 Node.js 的全副后劲,并构建高性能、可扩大且令人愉悦的开发体验。