nodejs 进程间通信方式,nodejs进程通信
节点如何相互通信?下面这篇文章带你了解节点进程的通信方式,以及如何在node中实现这些通信方式。希望对你有帮助!
node.js速度课程简介:进入学习
实际上,通信涵盖了开发的所有层面,如客户端与服务器之间通过各种通信协议的通信、RPC通信、开发过程中模块之间的通信、电子主进程与渲染进程之间的通信等。
本文主要尝试总结nodejs(单线程、多线程、多进程)的通信方式、使用场景和实现。
通信的实现方式
通用过程通信的实现如下:
1、共享内存(内存共享);
2.插座(插座);
3.管道(命名管道FIFO);
4.信号;
5.消息队列(message queue);
让我们来看看如何在node中实现这些通信方式。
一、Shared Memory(内存共享)
在单机上(客户端单线程,单进程多线程,单服务器多进程),内存共享是最常见的通信实现方式。
Shared Memory(内存共享)-单线程
从操作系统层面来说,一个进程中所有线程的内存是共享的,但前提是需要知道内存的访问地址。
但从语言层面(节点或v8实现层面)来说,我们并不直接接触内存管理,而是从v8提供的语法/api来间接做内存操作。V8为我们提供了三种共享内存的方式(或许称之为共享变量更合适):全局变量,局部变量,共享传参(通过共享调用);
v8在执行代码之前,会先通过Estree规范将代码转换成抽象的语法树,然后再进行解释、编译和执行。在抽象语法树中(见我另一篇关于抽象语法树的文章),有一个作用域,通过标识符(变量命名)一步步追溯内存读取。因此,如果您需要在两个方法之间共享一些内存,您可以在它们的公共范围内创建它。
Shared Memory(内存共享)-多线程
在客户端环境或者节点环境中,我们都可以实现多线程,两种方式类似(节点由Worker_threads实现,浏览器由Worker实现)。这里的内存共享主要是通过内存操作api(SharedArrayBuffer)来实现的。我们先来看看浏览器实现的例子:
//主线程
const buffer=new SharedArrayBuffer(1024)
const type darr=new int 16 array(buffer)
const newWorker=新工人(。/worker . js’)
typed ar[0]=20
newWorker.postMessage(缓冲区)
newWorker.onmessage=(data)={
console . group([主线程]);
console.log(从主线程接收的数据:%i ,type darr[0]);
console . groupend();
}
//子线程
addEventListener(message ,({ data })={
const arr=new Int16Array(data)
console . group([工作线程])
console.log(从主线程接收的数据:%i ,arr[0])
console.groupEnd()
arr[0]=18
postMessage(“已更新”)
})
//结果
[工作线程]
从主线程接收的数据:20
[主线程]
从主线程接收的数据:18:
Shared Memory(内存共享)-多进程
由于进程启动后内存不能互相读取(系统级限制),进程间的内存共享实际上是通过打开一个新的共享内存来实现的。不过node暂时不支持共享内存,只能用低级语言实现,比如C实现的shared-memory-interrupt或者addon插件(另文介绍)。
二、Socket(套接字)
套接字可以通过两种方式实现:
1、TCP套接字;
2、UNIX域套接字;
两者之间的主要区别如下:
TCP Socket适用于单机、C/S架构等。但是UNIX域套接字只适用于单机。
UNIX域Socket不需要经过一系列的网络传输(协议、分包、验证等。),所以性能更高,稳定性更好。
TCP Socket
概念:TCP Socket是应用层与TCP/IP协议族通信的中间抽象层,是操作系统提供的进程间通信机制;
TCP套接字通信应该是我们日常开发(C/S架构)中最常见的通信方式之一。我们日常开发中最常见的就是各种应用层协议的使用(http,websocket,rpc,ftp等。).节点中的http模块也是基于net模块实现的。
注意:其实UDP也属于TCP层(严格来说不是指TCP通信,而是网络通信层中的TCP/IP层)。node已经提供了‘dgram’模块来实现,但在实际应用中没有接触过,所以不得而知。
net
在node中,TCP Socket由net模块实现,主要提供以下功能:
1.上层的IPC支持(其实就是管道通信的实现,后面会详细说明);
2.网。服务器类;
//服务器通过net.createServer创建服务,返回一个net。服务器对象,并可以通过返回值端口监视器监视各种事件
const net=require(net )
net.createServer((server={
server.end(`hello world!\n `)
})).听着(3302,()={
console.log(`运行.`)
})3、网。套接字类;
const net=require(net )
const socket=net . create connection({ port:3302 })
socket.on(data ,data={
console.log(data.toString())
})
UNIX Domain Socket
UNIX域套接字是通过创建一个文件描述符来实现的,不同进程之间的通信是通过读写这个文件描述符来实现的(可以分为创建进程和其他进程,其他进程之间的通信可以通过创建进程来传递)。例如
//创建一个进程
const net=require(net )
const unixSocketServer=net . create server(server={
server.on(data ,data={
console.log(`接收数据:${data} `)
})
})
unixsocketserver . listen(/tmp/test ,()={
console.log(listening . )
})
//其他进程
const net=require(net )
const socket=net . create connection({ path:/tmp/test })
socket.on(data ,data={
console.log(data.toString())
})
socket.write(我的名字是vb )
//输出结果
倾听.
Receivedata:我叫VB:
三、管道
管道通信有两种,未命名管道和命名管道。
非命名管道的实现与UNIX域套接字相同,通过创建文件描述符进行通信。
命名管道通过固定的文件描述符进行通信:
\\\\.\\pipe\\ 管道名称;源代码可以参考stack overflow(https://stack overflow . com/questions/11750041/how-to-create-a-named-pipe-in-node-js)。
目前管道通信与UNIX域套接字的实现基本相同,只是管道通信规定了读写权限,半双工通信使UNIX域套接字更加自由。
四、Signal(信号)
信号是操作系统在终止进程之前发送给进程的信号。在节点中可以通过process.kill (PID,signal)/child _ process.kill (PID,signal)接口实现,例如.
//要终止的http守护进程
const Koa=require(koa )
const app=新Koa()
app.listen(3004,()={
console.log(`进程pid为:${process.pid}`) //进程pid为:75208
})
//操作流程
Process.kill (75208, sighup)//sighup 通常是一个结束进程的信号。还有更多其他信号可以参考【ID】(https://blog . csdn . net/houji Xin/article/details/71430489)。但这里的前提是,你需要得到被终止进程的pid。更大的
五、Message queue(消息队列)
一开始我以为是redis,各种基于MQ的消息队列。但是,它实际上是操作系统中的一个消息队列。节点暂时没有提供相关的上层接口,所以需要一个较低层的实现,比如svmq。
更多关于node的信息,请访问:nodejs教程!这就是节点中进程通信的几种实现方法的细节。请多关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。