创建具有负载平衡和集群的可扩展 Node.js 应用程序

news2024/11/25 1:28:22

创建具有负载平衡和集群的可扩展 Node.js 应用程序

负载平衡是提高应用程序性能、可扩展性和可用性的一项重要技术。当客户端向负载均衡器发出请求时,负载均衡器根据预定义的规则将请求分发到不同的实例。

可以使用cluster集群模块或 PM2 等工具根据负载均衡器的流量动态创建和删除实例。集群模块可用于创建工作进程,而PM2可用于进程管理、负载均衡、零停机部署、日志管理、进程集群和安全。

PM2Node.js 应用程序的流行流程管理器,提供了一系列有用的功能和优点,包括负载平衡和流程集群。为了使用 PM2 实现负载均衡,我们可以创建一个 Node.js 集群。Node.js 处理传入流量并将其分配给可用的工作进程。工作进程的最佳数量取决于应用程序的具体需求,并且应仔细优化性能和可扩展性。

在这里插入图片描述

负载均衡

首先,我们来讨论一下负载均衡的基本概念。负载均衡是一种在多个服务器之间分配传入网络流量的工具,以确保没有任何一台服务器因请求而不堪重负。负载均衡器可以使用硬件设备或软件程序来实现,它们通常使用算法来确定如何分配流量。

对于 Node.js,负载均衡可以在不同服务器上运行的多个 Node.js 实例之间分发传入的 HTTP 请求。这可以确保没有单个实例因请求而过载,从而提高性能和可靠性。

当客户端向负载均衡器发出请求时,负载均衡使用算法来确定哪个 Node.js 实例应处理该请求。可以使用多种不同的算法,包括:

  • 循环:此算法只是按顺序循环可用的 Node.js 实例,将每个新请求发送到序列中的下一个实例。
  • 最少连接:此算法选择收到请求时活动连接最少的 Node.js 实例。
  • IP 哈希:此算法计算客户端 IP 地址的哈希,并使用该值来确定哪个 Node.js 实例应处理该请求。这可以帮助确保来自同一客户端的请求始终发送到同一实例。

还有其他算法,例如随机、加权循环、加权最少连接、粘性会话,但这不在本文的讨论范围内。

一旦负载均衡确定哪个 Node.js 实例应处理该请求,它就会将该请求发送到该实例。如果实例已经运行并且可用,它将立即处理请求。但是,如果没有可用实例,负载均衡可以动态创建新实例来处理请求。

动态创建Node实例

动态创建新 Node.js 实例的一种方法是使用child_process工作进程模块。工作进程只是 Node.js 运行时的一个单独实例,可用于处理请求。要创建新的工作进程,可以使用child_process模块,如下所示:

const { fork } = require('child_process');

// 创建一个新的工作进程
const worker = fork('./worker.js');

// 监听来自工作进程的消息
worker.on('message', (msg) => {
  console.log(`Received message from worker: ${msg}`);
});

// 向工作进程发送消息
worker.send('Hello from the main process!');

在此示例中,我们使用child_process模块中的fork方法从名为worker的单独 Node.js 文件创建一个新的工作进程。然后,我们使用on('message')方法侦听来自工作进程的消息,每当工作进程将消息发送回主进程时就会调用该方法。我们还使用send()方法向工作进程发送消息,该方法将消息从主进程发送到工作进程。

以下是worker.js文件的示例:

// 监听来自主进程的消息
process.on('message', (msg) => {
  console.log(`Received message from main process: ${msg}`);

  // 向主进程发送消息
  process.send('Hello from the worker process!');
});

使用child_process实现负载均衡

以下是在 Node.js 中使用工作进程的实现负载均衡的示例:

const http = require('http');
const { fork } = require('child_process');
const url = require('url');

// 创建工作进程数组
const workers = [];

for (let i = 0; i < 4; i++) {
  workers.push(fork('./server.js'));
}

// 创建一个循环计数器
let counter = 0;

// 创建负载均衡
http.createServer((req, res) => {
  // 根据循环计数器获取下一个工作进程
  const worker = workers[counter];
  // 增加循环计数器
  counter = (counter + 1) % workers.length;
  // 发送到工作进程
  const parsedUrl = url.parse(req.url, true);
  worker.send({ path: parsedUrl.pathname });

  // 监听
  worker.on('message', (message) => {
    res.writeHead(200);
    res.end(message);
  });
}).listen(8000);

console.log('server running on port 8000');

在此代码中,我们首先通过fork创建server.js工作进程4次,并放入到数组。这将创建四个独立的 Node.js 运行时实例,每个实例运行自己的server.js代码副本。

server.js文件:

const http = require('http');
const https = require('https');

// 创建http服务
http.createServer((req, res) => {
  res.writeHead(301, { Location: `https://${req.headers.host}${req.url}` });
  res.end();
}).listen(80);

// 创建https服务
https.createServer(options, (req, res) => {
  // ...
}).listen(443);

然后,我们创建一个循环计数器变量,用于跟踪将每个传入请求发送到哪个工作进程。我们最初将计数器设置为零。

接下来,我们创建一个侦听端口 80HTTP 服务器。对于每个传入请求,我们根据循环计数器从工作程序数组中获取下一个工作进程。然后我们增加计数器以准备下一个请求。

我们使用send方法将传入请求发送到选定的工作进程。工作进程接收请求并使用process.send方法发回响应。我们设置一个消息监听器来接收来自worker.js的响应,并使用它来将响应发送回客户端。

在工作进程中,我们有以下代码:

const http = require('http');

// 以当前进程的ID创建一个 HTTP 服务器
http.createServer((req, res) => {
  res.writeHead(200);
  res.end(`Hello from worker ${process.pid}\n`);
}).listen(0, () => {
  console.log(`Worker ${process.pid} listening on port ${server.address().port}`);
});

// 设置消息侦听器以接收来自负载均衡的请求
process.on('message', (message) => {
  const server = http.createServer((req, res) => {
    res.writeHead(200);
    res.end(`Hello from worker ${process.pid}\n`);
  });

  server.listen(() => {
    process.send(`http://localhost:${server.address().port}${message.path}`);
  });
});

在此代码中,我们创建一个 HTTP 服务器,该服务器在收到请求时以当前进程 ID 进行响应。我们还设置了一个消息侦听器来接收来自负载均衡的传入请求。

当工作进程收到来自负载均衡器的消息时,它会创建一个新的 HTTP 服务器来侦听随机端口。然后,它将一条消息发送回负载均衡器,其中包含新服务器的 URL(包括请求的路径)。

负载均衡接收来自工作线程的响应并将其发送回客户端。客户端看到来自负载均衡的响应,就好像它直接来自工作进程一样,即使它实际上是由负载均衡转发的。

这是一个非常简单的负载均衡示例,它使用工作进程在多个 Node.js 实例之间分发传入请求。然而,这种实现有一些限制。例如,如果工作进程崩溃或变得无响应,负载均衡将继续向该工作进程发送请求,这可能会导致性能不佳或停机。

为了克服这个问题,我们可以使用更先进的负载均衡技术,例如健康检查或动态扩展。运行状况检查可用于监视工作进程的运行状况并从池中删除无响应的进程。动态扩展可用于根据流量模式或资源使用情况自动添加或删除工作进程。

除了work_process之外,Node.js 还具有一个内置cluster模块,可用于创建 Node.js 实例集群。cluster模块与工作进程类似,但它提供了更高级的功能,例如自动负载平衡和进程管理。

使用cluster实现负载均衡

以下是使用cluster模块在 Node.js 中创建负载均衡的示例:

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

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

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

  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} died`);
    cluster.fork();
  });
} else {
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('hello world\n');
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

在此示例中,我们使用cluster模块创建 Node.js 实例集群。isMaster属性检查当前进程是否为主进程,如果是,则代码使用cluster.fork()方法为每个可用 CPU 核心创建一个工作进程。

该代码还为exit事件设置了一个事件侦听器,该事件侦听器在工作进程终止时发出。当工作进程死亡时,事件侦听器会记录一条消息并派生一个新的工作进程来替换已死亡的工作进程。

如果当前进程不是主进程(即它是工作进程),则代码会设置一个 HTTP 服务器,该服务器侦听端口 8000 并使用“hello world”消息响应请求。

使用 PM2 进行负载平衡

PM2Process Manager 2 )是 Node.js 应用程序的流行流程管理器,它提供了一系列用于管理和扩展 Node.js 应用程序的有用功能。PM2 可用于流程监控、负载平衡、零停机部署、日志管理、流程集群和安全。

PM2 的主要功能之一是它能够为 Node.js 应用程序执行负载平衡。PM2 可用于跨多个 Node.js 进程分配传入流量,这有助于提高应用程序性能和可扩展性。PM2 还可以创建 Node.js 进程集群,这有​​助于利用多个 CPU 核心并提高应用程序性能和吞吐量。

以下是如何在 Node.js 应用程序中使用 PM2 进行负载平衡的示例:

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200);
  res.end(`Hello from process ${process.pid}\n`);
});

// 使用pm2
const cluster = require('pm2').clusterMode();

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  for (let i = 0; i < 4; i++) {
    cluster.fork();
  }
} else {
  server.listen(8000);
  console.log(`Worker ${process.pid} started`);
}

在此示例中,我们使用 Node.js中的http模块创建一个简单的 HTTP 服务器。然后,我们通过调用启用进程集群和负载平衡来使用 PM2 启动服务器。

如果当前进程是主进程,我们使用cluster.fork()来启动四个工作进程。每个工作进程将处理来自客户端的传入 HTTP 请求。如果当前进程是工作进程,我们通过调用启动 HTTP 服务器并记录一条消息以表明工作进程已启动。

当客户端向服务器发出请求时,PM2 将在可用的工作进程之间分配请求,这有助于提高应用程序性能和可扩展性。通过使用 PM2 进行负载平衡,我们可以确保 Node.js 应用程序能够处理高水平的流量并提供可靠且响应迅速的用户体验。

注意:在提供的示例代码中fork四个工作进程的决定是任意的,给定应用程序的最佳工作进程数量取决于可用 CPU 核心、应用程序大小和预期级别等因素的流量。
一般来说,建议每个 CPU 核心有一个工作进程,以最大限度地提高性能和可扩展性。但是,工作进程的最佳数量可能会根据应用程序的具体需求而有所不同。

如果我们的负载均衡过载,我们可以通过添加更多资源(例如额外的服务器或 CPU)来解决问题,或者通过优化代码或配置来减少服务器上的负载。我们还可以使用先进的负载均衡技术,例如动态扩展或自动扩展,根据流量模式自动调整 Node.js 实例的数量。

总结

负载平衡是提高 Node.js 应用程序性能和可靠性的一项重要技术。负载均衡器使用算法将传入流量分配到在多个服务器上运行的不同 Node.js 实例,并且可以使用work_process或者cluster模块等技术根据流量模式动态创建和删除 Node.js 实例。了解 Node.js 中的进程、子进程和进程生成对于构建可扩展且高效的 Node.js 应用程序也很重要。

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

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

相关文章

谈谈一个IT杂家的职业生涯规划,你的护城河被AI 攻破了么

文章大纲 没有顶会的从业者&#xff1a;成为深度学习老中医AIGC 还未能克服的难点&#xff1a;忽然的惊喜 -- 大模型的智能涌现未来还能做点什么&#xff0c;从计算机视觉的发展走向看T 字型人才与护城河成为更加熟练使用人工智能的人 参考文献与学习路径 我的职业生涯将近十年…

【多项式回归】拟合有噪声的正弦曲线

先导入模块并创建数据&#xff1a; from sklearn.preprocessing import PolynomialFeatures as PF from sklearn.linear_model import LinearRegression import numpy as nprnd np.random.RandomState(42) #设置随机数种子 X rnd.uniform(-3, 3, size100) y np.sin(X) rnd…

飞书开发学习笔记(六)-网页应用免登

飞书开发学习笔记(六)-网页应用免登 一.上一例的问题修正 在上一例中&#xff0c;飞书登录查看网页的界面显示是有误的&#xff0c;看了代码&#xff0c;理论上登录成功之后&#xff0c;应该显示用户名等信息。 最后的res.nickName是用户名&#xff0c;res.i18nName.en_us是英…

冲击900亿美元估值!邀约路演、秘密交表的Shein上市有望

双十一的狂欢刚刚结束&#xff0c;Shein即将赴美上市的消息又在电商圈里投下一枚重磅炸弹。 继被媒体曝光其寻求900亿美金估值后&#xff0c;最新的消息称其已邀请投资人参与路演&#xff0c;且已秘密完成交表。这个神秘的中国独角兽&#xff0c;离敲钟登陆美股的日子越来越近…

爬虫----robots.txt 协议简介

文章目录 robots.txt 是一个用于指示网络爬虫(web spider或web robot)如何与网站上的内容进行交互的协议。这个文件被网站管理员放置在网站的根目录下,用于告知爬虫哪些部分的网站是可以被抓取的,哪些是不被允许的。以下是 robots.txt 协议的一些关键要点: 控制爬虫访问:…

“技能兴鲁”职业技能大赛-网络安全赛项-学生组初赛 WP

Crypto BabyRSA 共模攻击 题目附件&#xff1a; from gmpy2 import * from Crypto.Util.number import *flag flag{I\m not gonna tell you the FLAG} # 这个肯定不是FLAG了&#xff0c;不要交这个咯p getPrime(2048) q getPrime(2048) m1 bytes_to_long(bytes(flag.e…

MHA的那些事儿

什么是MHA&#xff1f; masterhight availability&#xff1a;基于主库的高可用环境下&#xff0c;主从复制和故障切换 主从的架构 MHA至少要一主两从 出现的目的&#xff1a;解决MySQL的单点故障问题。一旦主库崩溃&#xff0c;MHA可以在0-30s内自动完成故障切换 MHA使用的…

毫米波雷达模块的目标检测与跟踪

毫米波雷达技术在目标检测与跟踪方面具有独特的优势&#xff0c;其高精度、不受光照影响等特点使其在汽车、军事、工业等领域广泛应用。本文深入探讨毫米波雷达模块在目标检测与跟踪方面的研究现状、关键技术以及未来发展方向。 随着科技的不断进步&#xff0c;毫米波雷达技术在…

深入解析 Azure 机器学习平台:架构与组成部分

Azure机器学习平台是Microsoft Azure提供的一种云上机器学习服务&#xff0c;为开发者和数据科学家提供了一个全面且易于使用的环境来创建、训练、部署和管理机器学习模型。本文将对Azure机器学习平台的基本架构和组成部分进行深入解析&#xff0c;帮助读者全面了解该平台的工作…

10-18 请求与相应1

前后台联调 前台通过一个表单, action写的servlet绑定的url,提交表单,请求我们servlet的doGet()/ doPost()方法 问题: 1.后台怎么获取前端的提交,请求的数据?底层:TCP通信,socket的得到输入流,读取数据 2.后台处理请求之后,怎么把结果给到前端?底层:TCP通信,socket的得到输入…

VR全景:打造虚拟政务服务,打通服务群众“最后一公里”

大家对政务大厅的工作效率可能已经司空见惯&#xff0c;办事窗口少&#xff0c;而需要办理的群众和业务却很多&#xff0c;很多去政务大厅办理业务的&#xff0c;排队几个小时也是常有的。并且在传统政务服务中&#xff0c;办事流程一般都较为复杂、耗时长&#xff0c;往往需要…

TSINGSEE视频汇聚管理与AI算法视频质量检测方案

一、建设背景 随着互联网视频技术的发展&#xff0c;视频监管在辅助安全生产、管理等方面发挥了不可替代的作用。但是&#xff0c;在监管场景中&#xff0c;仍然存在视频掉线、视频人为遮挡、视频录像存储时长不足等问题&#xff0c;对企业的日常管理和运转存在较大的安全隐患…

uniapp插件开发

安装android studio&#xff1a;安装目录下bin下的此文件&#xff0c;是用来修改分配给android studio的占用内存。 Android 11足够用。 创建新项目&#xff1a; 目录结构介绍&#xff1a; UI组件介绍&#xff1a;在设计程序界面时可以使用可视化拖拽的方式&#xff0c;没有必要…

DGL如何表征一张图

有关于DGL中图的构建 DGL 将有向图表示为一个 DGL 图对象。图中的节点编号连续&#xff0c;从0开始。我们一般通过指定图中的节点数&#xff0c;以及源节点和目标节点的列表&#xff0c;来构建这么一个图。 下面的代码构造了一个图&#xff0c;这个图有五个叶子节点。中心节点…

03 # 类型基础:动态类型与静态类型

通俗定义 静态类型语言&#xff1a;在编译阶段确定所有变量的类型 编译阶段确定属性偏移量用偏移量访问代替属性名访问偏移量信息共享 动态类型语言&#xff1a;在执行阶段确定所有变量的类型 在程序运行时&#xff0c;动态计算属性偏移量需要额外的空间存储属性名所有对象的…

246:vue+openlayers 绘制多边形,drawend获取最大幅宽

第246个 点击查看专栏目录 本示例是演示如何在vue+openlayers项目中绘制多边形,drawend获取最大幅宽。这里利用turf的turf.distance和openlayers的getExtent获取坐标值。 距离赤道越近,幅宽会越大一些,这里面利用了Math.abs来做绝对值的判断处理。 直接复制下面的 vue+open…

HBase学习笔记(3)—— HBase整合Phoenix

目录 Phoenix Shell 操作 Phoenix JDBC 操作 Phoenix 二级索引 HBase整合Phoenix Phoenix 简介 Phoenix 是 HBase 的开源 SQL 皮肤。可以使用标准 JDBC API 代替 HBase 客户端 API来创建表&#xff0c;插入数据和查询 HBase 数据 使用Phoenix的优点 在 Client 和 HBase …

docker-compose 部署 MySQL 8

前言 Windows 系统通过 docker-compose 部署 MySQL8.0。 MySQL 配置文件(my.cnf) # 服务端参数配置 [mysqld] usermysql # MySQL启动用户 default-storage-engineINNODB # 创建新表时将使用的默认存储引擎 character-set-serverutf8mb4 # 设置mysql服…

科研学习|科研软件——有序多分类Logistic回归的SPSS教程!

一、问题与数据 研究者想调查人们对“本国税收过高”的赞同程度&#xff1a;Strongly Disagree——非常不同意&#xff0c;用“0”表示&#xff1b;Disagree——不同意&#xff0c;用“1”表示&#xff1b;Agree--同意&#xff0c;用“2”表示&#xff1b;Strongly Agree--非常…

从0到0.01入门 Webpack| 002.精选 Webpack面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…