扩展 Node JS 应用

Isaac Tony 2023年10月12日
  1. 使用集群模块扩展 Node JS 应用程序
  2. Node JS 中的微服务
  3. Node JS 中的分片和分区
扩展 Node JS 应用

可扩展性是应用程序能够继续为用户提供服务而不会失败,即使工作量增加也是如此。因此,扩展是增加计算、存储或网络资源以优化资源利用率并满足用户增加的流量的过程。

还可以进行扩展以减少故障,从而提高服务的可用性。缩放有两种类型:向上缩放、垂直缩放和向外缩放,也称为水平缩放。

众所周知,Node JS 是一种单线程语言,一次只允许执行一个进程。但是,我们可以通过集群模块等功能利用现代计算机中的多个 CPU 内核,而不会耗尽 RAM。

除此之外,使用这个模块,如果需要,我们可以轻松地重新启动我们的应用程序,而不会经历极端的停机时间。此外,Node JS 的异步和非阻塞特性允许我们同时执行多个进程而不会使服务器过载。

现在在 Node JS 中,我们可以使用不同的策略来扩展 Node JS 应用程序,其中一些将在下面讨论。

使用集群模块扩展 Node JS 应用程序

cluster 模块允许我们创建多核系统,而不是依赖 Node JS 的单线程特性。

使用这个模块,我们可以创建多个子进程,称为 worker,它们在同一个服务器端口上运行。这意味着随着工作量的增加,我们可以处理所有的用户请求,从而增加进程中的服务器吞吐量。

几个子进程允许我们在不阻塞其他操作的情况下处理多个请求。这主要是因为每个进程/工作者都在其事件线程上运行,并在引擎和内存中分配了其实例。

如前所述,无论如何,如果我们想重新启动我们的应用程序或将新的更新推送到生产环境,使用集群模块可以让我们减少停机时间。这是因为我们可以让一些子进程运行,而我们在任何时候处理其余的进程。

我们可以通过首先拥有一个主要职责是处理所有传入请求的主进程来实现这种方法。然后,主进程将分叉子进程并使用循环算法为它们分配一个要处理的请求。

与其他算法不同,轮循算法不会按优先级为子进程/工作者分配角色,而是按编号分配角色。第一个请求被分配给第一个可用的子进程。

如此处所示,我们可以创建共享端口 8080 的主进程和子进程。

const cluster = require('cluster');
const cpu_cores = require('os').cpus().length;
const process = require('process');
const http = require('http');

if (cluster.isPrimary) {
  console.log(`Main Process ${process.pid} is running`);

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

  cluster.on('exit', (worker, code, signal) => {
    console.log(`This worker ${worker.process.pid} has died`);
  });
} else {
  http.createServer((req, res) => {
        res.writeHead(200);
        res.end(' This is the end\n');
      })
      .listen(8080);

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

输出:

Main Process 10928 is running
Child Process 13664 is running
Child Process 10396 is running
Child Process 2952 is running
Child Process 9652 is running

Node JS 中的微服务

微服务是一种设计模式,它允许我们将应用程序分解为松散耦合的独立功能单元,这些单元可以独立地进行测试、部署和扩展。

每个功能单元或服务都有一个专用的数据库和接口。使用这种架构时,主要关注点通常是确保服务是松散耦合的,而不是最小化它们的大小。

当与非阻塞特性相结合时,Node JS 和微服务允许开发人员将大型企业应用程序分解为模块化结构。每个组件都可以分配给专用资源并仅在必要时进行扩展。

除了在 Node JS 应用程序中使用这种架构的卓越性能外,它还具有成本效益,并允许开发人员构建处理巨大工作负载的高度可扩展的应用程序。

Node JS 中的分片和分区

这些概念在构建可扩展的数据库架构中很常见。尽管有时它们暗示着同样的事情,但事实并非如此。

分片使我们能够实现水平分区。在使用 Node JS 构建数据密集型应用程序时,我们可以将数据划分为单独的服务器实例,从而减少单个服务器的负载。

划分这些数据的依据是我们所说的 Shady key。例如,我们可以决定根据用户的地理位置对数据进行细分。

另一方面,分区使我们能够使用稍微不同的方法来扩展我们的 Node JS 应用程序。在返回适当的响应之前,每个应用程序通常都会扫描数据库中的请求数据。

我们可以将大型数据库表拆分为较小的表,以减少响应时间,并使我们的 Node JS 应用程序即使在工作负载增加时也具有更高的响应性。这使我们的 Node JS 应用程序可以轻松扫描数据并快速返回响应。

你可以使用更多方法来扩展 Node JS 应用程序。随着更现代的工具(如 Amazon CloudFront、Redis)和现代负载均衡器(如 Nginx Plus 或 AWS 的 ELB)的出现,构建更具可扩展性的应用程序变得越来越容易。

作者: Isaac Tony
Isaac Tony avatar Isaac Tony avatar

Isaac Tony is a professional software developer and technical writer fascinated by Tech and productivity. He helps large technical organizations communicate their message clearly through writing.

LinkedIn