千家信息网

node中进程通信的实现方式有哪些

发表于:2024-11-23 作者:千家信息网编辑
千家信息网最后更新 2024年11月23日,这篇文章主要介绍"node中进程通信的实现方式有哪些",在日常操作中,相信很多人在node中进程通信的实现方式有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"nod
千家信息网最后更新 2024年11月23日node中进程通信的实现方式有哪些

这篇文章主要介绍"node中进程通信的实现方式有哪些",在日常操作中,相信很多人在node中进程通信的实现方式有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"node中进程通信的实现方式有哪些"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

通信其实涵盖开发的各个层面,常见的有客户端和服务端通过各种通信协议进行通信,RPC通信,开发过程中各个模块之间的相互通信,electron主进程和渲染进程之间的通信等等;

本文主要是尝试总结下nodejs(单线程,多线程,多进程)通信的方式,使用场景,实现等。

通信的实现方式

一般进程通信的实现方式如下:

1、Shared Memory(内存共享);

2、Socket(套接字);

3、管道(非命名管道Pipe, 命名管道FIFO);

4、Signal(信号);

5、Message queue(消息队列);

下面我们看下在node中如何实现这些方式的通信

一、Shared Memory(内存共享)

单机下(客户端内单线程,单进程里多线程,单台服务器内多进程),通过内存共享实现通信的方式最为常见。

Shared Memory(内存共享)-单线程

从操作系统层面来看,进程内所有线程内存都是共享的,但前提是需要知道内存的访问地址。

但从语言层面(node或者说是v8的实现层面),我们没有直接接触内存的管理,而是间接从v8提供的语法/api进行内存操作。v8提供三种方式给我们共享内存(也许叫共享变量更恰当):全局变量, 局部变量, 共享传参(call by sharing);

v8在执行代码之前会先将代码通过Estree规范转化为抽象语法树后再进行解释编译执行,在抽象语法树中(关于抽象语法树可查看我另外一篇文章)是有scope的,而内存读取是通过标志符(变量命名)逐级往上回溯查找。所以如果你需要在两个方法之间共享某个内存,可以在他们共同的作用域下进行创建。

Shared Memory(内存共享)-多线程

在客户端环境或node环境,我们都可以实现多线程,两者方式也类似(node通过worker_threads实现,浏览器通过Worker实现)。这里的内存共享主要是借助内存操作的api(SharedArrayBuffer)实现的。先看下浏览器实现的例子:

// 主线程const buffer = new SharedArrayBuffer(1024)const typedArr = new Int16Array(buffer)const newWorker = new Worker('./worker.js')typedArr[0] = 20newWorker.postMessage(buffer)newWorker.onmessage= (data) => {    console.group('[the main thread]');    console.log('Data received from the main thread: %i', typedArr[0]);    console.groupEnd();}// 子线程addEventListener('message', ({ data }) => {  const arr = new Int16Array(data)  console.group('[the worker thread]')  console.log('Data received from the main thread: %i', arr[0])  console.groupEnd()  arr[0] = 18    postMessage('Updated')})// 结果[the worker thread]  Data received from the main thread: 20[the main thread]  Data received from the main thread: 18

Shared Memory(内存共享)-多进程

因为进程启动后内存是无法相互读取的(系统层面的限制),进程之间的内存共享实际是通过新开辟一段shared memory实现的。但node暂时没有支持shared memory,只能通过低级语言来实现,例如: c++实现的 shared-memory-disruptor addon插件(另外文章介绍)。

二、Socket(套接字)

Socket 分两种实现:
1、TCP Socket;
2、UNIX Domain Socket;
两者的主要区别如下:

TCP Socket适用于单机,C/S架构等.但UNIX Domain Socket只适用于单机。  UNIX Domain Socket不需要经过一系列的网络中转(协议,分包,校验等等),性能更高,稳定性更好。

TCP Socket

概念: TCP Socket是应用层与TCP/IP协议族通信的中间抽象层,是一种操作系统提供的进程间通信机制;

TCP Socket通信应该是我们日常开发(C/S架构)中最常见的通信方式之一,在我们日常开发中最常见的就是各种应用层协议(http,websocket,rpc,ftp等)的使用,node中http模块也是基于net模块实现的。

注:其实UDP也属于TCP分层(并不是严格的指TCP通信,而是网络通信层中的TCP/IP层),node有提供'dgram'模块来实现,但在实际应用中没有接触过,所以不进行了解。

net

在node中,TCP Socket是由net模块实现的,net模块主要提供了以下功能:

1、上层的IPC支持(实际上是管道通信的实现,后面管道通信再详细说明);

2、net.Server类;

// 服务端通过net.createServer创建服务,会返回net.Server对象,可以通过返回值进行各种事件监听,端口监听const net = require('net')net.createServer((server => {  server.end(`hello world!\n`)})).listen(3302, () => {  console.log(`running ...`)})

3、net.Socket类;

const net = require('net')const socket = net.createConnection({port: 3302})socket.on('data', data => {  console.log(data.toString())})

UNIX Domain Socket

UNIX Domain Socket是通过创建一个文件描述符,不同进程之间的通信通过读写这个文件描述符进行通信(可以分为创建进程和其他进程,其他进程之间的相互通信可以通过创建进程作为中转)。e.g.

// 创建进程const net = require('net')const unixSocketServer = net.createServer(server => {  server.on('data', data => {    console.log(`receive data: ${data}`)  })})unixSocketServer.listen('/tmp/test', () => {  console.log('listening...')})// 其他进程const net = require('net')const socket = net.createConnection({path: '/tmp/test'})socket.on('data', data => {  console.log(data.toString())})socket.write('my name is vb')// 输出结果listening...receive data: my name is vb

三、管道

管道通信分两种,非命名管道和命名管道。
非命名管道的实现方式和UNIX Domain Socket一样,都是通过创建文件描述符进行通信。
命名管道是通过固定的文件描述符进行通信:

"\\\\.\\pipe\\" + PIPE_NAME;

源码可参考stackoverflow(https://stackoverflow.com/questions/11750041/how-to-create-a-named-pipe-in-node-js)
目前理解的管道通信和UNIX Domain Socket实现基本一致,只是管道通信规范了读写权限,半双工通信,UNIX Domain Socket更加自由一些。

四、Signal(信号)

Signal是操作系统在终止进程前给进程发送的信号。在node中可以通过process.kill(pid, signal)/child_process.kill(pid, signal)接口实现,e.g.

// 要被终止的http守护进程const Koa = require('koa')const app = new Koa()app.listen(3004, () => {  console.log(`process pid is : ${process.pid}`) // process pid is : 75208})// 操作进程process.kill(75208, 'SIGHUP') // 'SIGHUP'是一般结束进程的信号,还有更多其他的信号参考 [标识](https://blog.csdn.net/houjixin/article/details/71430489)

但这里的前提是你需要获取到被终止的进程pid,更多pid的内容可阅读我之前关于进程的文章。

五、Message queue(消息队列)

一开始我以为是redis,各种MQ之类的基于TCP的消息队列。但其实是操作系统内的消息队列,node暂时没有提供相关的上层接口,需要更底层实现,e.g. svmq

到此,关于"node中进程通信的实现方式有哪些"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

通信 进程 内存 方式 管道 线程 之间 模块 信号 层面 系统 操作系统 变量 常见 文件 更多 消息 语法 队列 学习 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 大学生网络安全演讲稿 国有企业软件开发也加班多 数据库建好表格无法保存 软件开发多国语言包开发 南昌网络安全信息委员会成员 嘉定区常规软件开发服务大概费用 ibm服务器 远程管理卡 瑞友科技数据库工程师面试 部门述职报告软件开发 电脑修改dns服务器安全吗 互联网农业科技公司创业计划 深圳市百保网络技术 网络安全边 如何避免网络安全的危害 优质产品数据库 广东中山五金模具erp软件开发 静安区创新数据库服务商销售 表空间上有哪些数据库用户 网络安全的数据分析岗位 数据库system初始密码 淄博分销软件开发哪家做的好 我的世界不开服务器就没有权限吗 国家网络安全检查工作指南 互联网科技公司股权 海南通用软件开发哪里好 数据通信领域最新网络技术 国铁集团网络安全事件调查 云服务器爬虫 全球微生物保藏机构数据库 计算机行业软件开发难不难
0