iis服务器助手广告广告
返回顶部
首页 > 资讯 > 服务器 >Nodejs搭建多进程Web服务器实现过程
  • 849
分享到

Nodejs搭建多进程Web服务器实现过程

Nodejs搭建多进程Web服务Nodejs搭建Web 2022-11-13 18:11:32 849人浏览 安东尼
摘要

目录前言父子进程间通信负载均衡句柄传递集群子进程事件自动重启总结前言 上节我们讲到,通过 fork() 或者其他api,创建子进程之后,可以通过 send() 和 process.o

前言

上节我们讲到,通过 fork() 或者其他api,创建子进程之后,可以通过 send()process.on('message') 进行父子进程间的通信。这样就实现了主进程代理请求到工作进程,实现了 nodejs集群

父子进程间通信

负载均衡

通过代理,可以避免端口不能重复监听的问题,甚至可以在代理进程上做适当的负载均衡,使得每个子进程可以较为均衡地执行任务。下面我们构建了一个简单的 WEB 服务器,并实现在两个工作进程之间做简单的负载均衡。

主进程,负责代理到对应进程中:

// main.js
const { fork } = require('child_process');
const nORMal = fork('subprocess.js', ['normal']);
const special = fork('subprocess.js', ['special']);
// Open up the server and send Sockets to child. Use pauseOnConnect to prevent
// 套接字在发送给子进程之前不会被读取
const server = require('net').createServer({ pauseOnConnect: true });
let flag = 0;
server.on('connection', (socket) => {
  flag++;
  // this is special priority.
  if (flag % 2 === 0) {
    special.send('socket', socket);
    return;
  }
  // This is normal priority.
  normal.send('socket', socket);
});
server.listen(1337);

这是工作进程,接收socket对象并做出响应:

// subprocess.js
process.on('message', (m, socket) => {
  if (m === 'socket') {
    // Check that the client socket exists. 
    // It is possible for the socket to be closed between the time it is
    if (socket) {
      // console.log(`Request handled with ${process.argv[2]} priority`);
      socket.end(`Request handled with ${process.argv[2]} priority, running on ${process.pid}`);
    }
  }
});

然后我又编写了一个 nodejs 脚本,来发出十个 Http 请求:

const cp = require("child_process");
for (let i = 0; i < 10; i++) {
  cp.exec(`curl --http0.9 "http://127.0.0.1:1337"`, (err, stdout, stderr) => {
    console.log(`finished: ${i}, and received: `, stdout);
  })
}

最后运行结果如下:

句柄传递

在使用 send() 方法时,我们注意到,除了能通过IPC发送数据外,还能发送句柄。第二个可选参数就是一个句柄:

child.send(message, [sendHandle]);

? 句柄是一种可以用来标识资源的引用,它的内部包含了指向对象的文件描述符。比如句柄可以用来标识一个服务器端socket对象、一个客户端socket对象、一个UDP套接字、一个管道等。

在主进程将句柄发送给子进程之后,工作模型就从主进程响应用户请求变成了子进程监听用户活动:

进程对象send()方法可以发送的句柄类型包括如下几种:

  • net.Socket。tcp套接字。
  • net.Server。TCP服务器,任意建立在TCP服务上的应用层服务都可以享受到它带来的好处。
  • net.Native。c++层面的TCP套接字或IPC管道。
  • dgram.Socket。UDP套接字。
  • dgram.Native。C++层面的UDP套接字。

? 另外要注意,send()方法能发送消息和句柄并不意味着它能发送任意对象,message 参数和文件句柄都要先通过 JSON.stringfy() 进行序列化后再放入IPC通道中:

集群

通过 child_process模块,我们完成了父子进程的创建和通信,已经初步搭建了一个Node集群。还有一些问题需要考虑:

  • 性能问题。
  • 多个工作进程的存活状态管理。
  • 工作进程的平滑重启。
  • 配置或者静态数据的动态重新载入。
  • 其他细节。

这其中最重要的便是集群的稳定性,这决定了该服务模型能否真正用于实践生成中。虽然我们创建了很多工作进程,但每个工作进程依然是在单线程上执行的,它的稳定性还不能得到完全的保障。我们需要建立起一个健全的机制来保障Node应用的健壮性。

子进程事件

父进程能监听到的,与子进程相关的事件:

  • error:当子进程无法被复制创建、无法被杀死、无法发送消息时会触发该事件。
  • exit:子进程退出时触发该事件。如果是正常退出,这个事件的第一个参数为退出码,否则为null。如果进程是通过kill()方法被杀死的,会得到第二个参数,它表示杀死进程时的信号。
  • close:在子进程的标准输入输出流中止时触发该事件,参数与exit相同。
  • disconnect:在父进程或子进程中调用disconnect()方法时触发该事件,在调用该方法时将关闭监听IPC通道

除了 send() 外,还能通过 kill() 方法给子进程发送消息。kill() 方法并不能真正地将通过IPC相连的子进程杀死,它只是给子进程发送了一个系统信号。默认情况下,父进程将通过 kill() 方法给子进程发送一个 SIGTERM信号

// 子进程
child.kill([signal]);
// 当前进程
process.kill(pid, [signal]);
// 监听
process.on(signal, callback)

? 在POSIX标准中,有一套完备的信号系统,在命令行中执行kill -l可以看到详细的信号列表,如下所示:

而 Node 提供了这些信号对应的信号事件,每个进程都可以监听这些信号事件。这些信号事件是用来通知进程的,每个信号事件有不同的含义,进程在收到响应信号时,应当做出约定的行为:

process.on('SIGTERM', () => {
    console.log("Got sigterm, exiting...");
    process.exit(1);
});
console.log("process running on: ", process.pid);
process.kill(process.pid, "SIGTERM");

自动重启

有了父子进程之间的相关事件之后,就可以在这些关系之间创建出需要的机制了,至少我们能够通过监听子进程的 exit事件 来获知其退出的信息。接着前文的多进程架构,我们在主进程上要加入一些子进程管理的机制,比如重新启动一个工作进程来继续服务:

主进程代码:

// master.js
// master.js
const { fork } = require('child_process');
const cpus = require('os').cpus();
const server = require('net').createServer();
server.listen(1337);
const workers = {};
// process.on('uncaughtException', function (err) {
//   console.log(`Master uncaughtException:\r\n`);
//   console.log(err);
// });
const createWorker = () => {
  const worker = fork('./worker.js');
  // 收到信号后立即重启新进程
  worker.on('message', function (message) {
    if (message.act === 'suicide') {
      createWorker();
    }
  });
  // 某个进程终止时重新启动新的进程
  worker.on('exit', () => {
    console.log('Worker ' + worker.pid + ' exited.');
    delete workers[worker.pid];
    // createWorker();
  });
  // 句柄转发
  worker.send('server', server);
  workers[worker.pid] = worker;
  console.log('Create worker. pid: ' + worker.pid);
};
for (let i = 0; i < cpus.length; i++) {
  createWorker();
}
// server.close();
// 进程自己退出时,让所有工作进程退出
process.on('exit', () => {
  for (let pid in workers) {
    workers[pid].kill();
  }
});

子进程代码:

// worker.js
const http = require('http');
const server = http.createServer((req, res) => {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('handled by child, pid is ' + process.pid + '\n');
  // 抛出异常,捕获后终止进程
  throw new Error('throw exception');
});
var worker;
process.on('message', (m, tcp) => {
  if (m === 'server') {
    worker = tcp;
    worker.on('connection', (socket) => {
      server.emit('connection', socket);
    });
  }
});
// 捕获异常后终止进程
process.on('uncaughtException', (err) => {
  // 主动发出信号,避免等待连接断开时收到新请求而缺少进程无法响应
  process.send({
    act: 'suicide'
  });
  // 停止接收新的连接
  worker.close(function () {
    // 所有已有连接断开后,退出进程
    process.exit(1);
  });
  // 避免长连接请求长时间无法终止,5s后自动终止
  setTimeout(() => {
    process.exit(1);
  }, 5000)
});

运行父进程 master.js,控制台中会打印出开启的进程 PID

linux 中,你可以直接使用 kill -9 [pid] 来终止进程。在 windows 中,你需要打开任务管理器,找到 node.exe 的进程,终止其中某个。此时命令行会显示该进程被终止了,然后重新开启一个新的进程。

当然,你也可以使用我们之前写的 run.js 脚本,每发起一个请求,子进程响应请求之后会抛出一个异常,异常在捕获之后会终止该进程。

? 我们之前写的 run.js 脚本是并行执行的,此时会存在多个请求被分配到同一个 socket ,即分配到同一个进程中执行。那么就会存在互斥的问题,即某个请求结束后就终止该进程,导致其他请求无法获得响应而终止。此时你需要将 exec 方法改为同步方法:

const cp = require("child_process");
const cpus = require("os").cpus();
const sleep = (delay) => {
  const now = Date.now();
  while (Date.now() - now < delay);
  return;
}
for (let i = 0; i < cpus.length; i++) {
  const out = cp.execSync(`curl --http0.9 "http://127.0.0.1:1337"`);
  sleep(1000);
  console.log(out.toString());
}

该模型一旦有异常出现,主进程会创建新的工作进程来为用户服务,旧的进程一旦处理完已有连接就自动断开。整个过程使得我们的应用的稳定性和健壮性大大提高:

总结

至此,我们完成了一个简单的基于父子进程通信、具备异常重启进程功能的 Web服务器 就已经搭建完成了。对于 Nodejs 多进程编程你也有了初步的了解。接下来我们将介绍 cluster模块,并介绍一下在 Nodejs 中进行多线程编程。

以上就是Nodejs搭建多进程Web服务器实现过程的详细内容,更多关于Nodejs搭建多进程Web服务器的资料请关注编程网其它相关文章!

--结束END--

本文标题: Nodejs搭建多进程Web服务器实现过程

本文链接: https://www.lsjlt.com/news/169697.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Nodejs搭建多进程Web服务器实现过程
    目录前言父子进程间通信负载均衡句柄传递集群子进程事件自动重启总结前言 上节我们讲到,通过 fork() 或者其他API,创建子进程之后,可以通过 send() 和 process.o...
    99+
    2022-11-13
    Nodejs搭建多进程Web服务 Nodejs搭建Web
  • Rust多线程Web服务器搭建过程
    目录最后的项目:多线程 Web 服务器构建多线程 Web 服务器优雅的停机和清理最后的项目:多线程 Web 服务器 构建多线程 Web 服务器 在 socket 上监听 TCP 连接...
    99+
    2023-05-17
    rust多线程 Web 服务器 rust Web 服务器
  • nodejs web本地服务器搭建
    随着web技术的不断发展,越来越多的人开始关注如何搭建一个本地的web服务器,以方便他们进行开发和测试工作。而Node.js作为一款非常流行的服务器端开发框架,也可以用于搭建web本地服务器。本文将介绍如何使用Node.js来搭建一个简单的...
    99+
    2023-05-17
  • 云服务器的搭建过程
    云服务器的搭建过程比较复杂,一般需要进行以下几个步骤: 选择云服务器平台:选择一个合适的云服务器平台是搭建云服务器的第一步,也是关键的一步。在选择云服务器平台时,需要考虑平台的性能、稳定性、安全性、可靠性等因素。可以通过比较不同云服务器...
    99+
    2023-10-26
    过程 服务器
  • nodejs搭建web服务器的缺点有哪些
    这篇文章将为大家详细讲解有关nodejs搭建web服务器的缺点有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 nodejs搭建web服务...
    99+
    2024-04-02
  • 巨杉Tech | 使用 SequoiaDB + Docker + Nodejs 搭建 Web 服务器
    容器化技术的出现大大简化了应用开发人员在构建底层基础设施的工作。SequoiaDB 巨杉数据库于3.2.1版本正式推出了 Docker 容器化部署方案,本文将会基于 SequoiaDB 巨杉数据库与Nod...
    99+
    2024-04-02
  • 云服务器的搭建过程包括
    首先,服务器硬件选择是非常重要的一步。在选择服务器硬件时,应该考虑以下几个因素:性能、可靠性、稳定性、可扩展性和安全性。例如,如果您正在运行大型数据中心,您需要选择处理能力强、稳定性高的服务器。如果您的网站需要快速响应,您需要选择具有高可扩...
    99+
    2023-10-28
    过程 服务器
  • TCP服务器实现—多进程版,多线程版,线程池版
    目录 前言 1.存在的问题 2.多进程版 3.多线程版 4.线程池版 总结 前言         在上一篇文章中使用TCP协议实现了一个简单的服务器,可以用来服务端和客户端通信,但是之前的服务器存在一个问题,就是当有多个客户端连接服...
    99+
    2023-08-31
    服务器 tcp/ip 运维
  • 如何通过nodejs快速搭建一个服务器
            在前端开发过程中,可能某些时候需要自己搭建一台服务器用于一些文件图片请求或者进行后端相关知识的学习。本文主要讲解如何通过nodejs进行一个基础服务器的搭建,包括如何将文件布置的服务器,以及基础接口的开发。后面可能会更新关于...
    99+
    2023-09-01
    前端 javascript 开发语言 node.js
  • windows系统搭建WEB服务器详细教程
    本文实例为大家分享了windows系统搭建WEB服务器的具体代码,供大家参考,具体内容如下 1.WEB服务器也称为网页服务器或HTTP服务器 2.WEB服务器使用的协议是HTTP或H...
    99+
    2022-11-13
    windows系统搭建WEB服务器 windows搭建服务器 windows搭建WEB服务器
  • linux搭建web服务器的流程是什么
    搭建Linux上的Web服务器的一般流程如下: 选择和安装操作系统:选择一个适合的Linux操作系统,如Ubuntu、CentOS...
    99+
    2024-02-29
    linux 服务器
  • 服务器SVN搭建图文安装过程
    目录一、首先准备三个软件:二、安装一、首先准备三个软件: 1.VisualSVN-Server-3.6.3-x64.msi(svn服务端) 2.TortoiseSVN-1.9.6.2...
    99+
    2024-04-02
  • 云服务器的搭建过程是什么
    云服务器(Cloud Storage)是一种使用虚拟化技术构建的服务器,它通过互联网连接计算机和其他设备,并通过虚拟化技术将所有资源统一管理。使用云服务器可以让人们通过互联网访问、使用云计算资源、管理虚拟服务器和应用程序,从而降低了IT管理...
    99+
    2023-10-26
    过程 服务器
  • Yolov5服务器环境搭建详细过程
    目录1 服务器搭建yolov5环境1.1 创建环境1.2 跟随官方指引2 下载预训练权重3 推理4 测试1 服务器搭建yolov5环境 1.1 创建环境 首先先的在本地环境下搭建一个...
    99+
    2024-04-02
  • Linux搭建DHCP服务器的详细过程
    DHCP协议简介 DHCP(动态主机配置协议)是一个局域网的网络协议。指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。DHCP(Dynamic Host Configu...
    99+
    2024-04-02
  • WEB通讯技术。前端实现SSE长连接,nodejs+express搭建简单服务器,进行接口调试,通过curl请求数据
    描述 长连接(Keep-Alive)是一种HTTP/1.1的持久连接技术,它允许客户端和服务器在一次TCP连接上进行多个HTTP请求和响应,而不必为每个请求/响应建立和断开一个新的连接。长连接有助于减少服务器的负载和提高性能。 长连接的HT...
    99+
    2023-08-19
    服务器 前端 express
  • 个人web服务器搭建的流程是什么
    1. 选择服务器操作系统:可以选择Linux、Windows等操作系统,其中Linux操作系统比较常用。2. 安装服务器软件:根据所...
    99+
    2023-05-13
    个人web服务器 服务器
  • docker搭建es集群实现过程详解
    目录前言什么是es使用docker搭建es集群前言 该系列默认开启Nacos 服务,还不会搭建的小伙伴可以参考往期文章~ 本节重点是给大家介绍利用docker来搭建Es集群,废话...
    99+
    2023-01-31
    docker搭建es集群 es集群搭建
  • 腾讯云服务器搭建多ip教程
    腾讯云服务器搭建多ip有很多种方式,以下是其中一种常见的方法: 1、使用多台云服务器进行负载均衡:使用一台服务器来均衡多个ip地址,将它们连接到同一个服务器。这可以避免服务器之间的负载不均衡,从而减少网络延迟和故障的可能性。 2、使用负载...
    99+
    2023-10-26
    腾讯 服务器 教程
  • Python本地搭建静态Web服务器的实现
    目录静态Web服务器-返回固定页面数据1. 开发自己的静态Web服务器2. 静态Web服务器-返回固定页面数据的示例代码3. 小结静态Web服务器-返回指定页面数据1. 静态Web服...
    99+
    2023-02-01
    Python搭建静态Web服务器 Python 静态Web服务器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作