Home >Web Front-end >JS Tutorial >Detailed explanation of several implementation methods of process communication in node
nodeHow to communicate between processes? The following article will help you understand the communication methods of node processes and how to implement these methods of communication in node. I hope it will be helpful to you!
Communication actually covers all levels of development. Common ones include client and server communicating through various communication protocols, RPC communication, and communication between various modules during the development process. Mutual communication, communication between the main electron process and the rendering process, etc.;
This article mainly tries to summarize the nodejs (single-threaded, multi-threaded, multi-process) communication methods, using Scenarios, implementations, etc.
General process communication is implemented as follows:
1. Shared Memory (memory sharing);
2. Socket (socket);
3. Pipe (non-named pipe Pipe, named pipe FIFO);
4. Signal (signal);
5 , Message queue (message queue);
Let’s take a look at how to implement these methods of communication in node
Stand-alone ( Single thread in the client, multiple threads in a single process, multiple processes in a single server), communication through memory sharing is the most common way.
From the operating system level, all thread memory in the process is shared, but the premise is that the memory needs to be known access address.
But from the language level (node or v8 implementation level), we do not directly touch memory management, but indirectly perform memory operations from the syntax/api provided by v8. v8 provides us with three ways to share memory (maybe more appropriately called shared variables): global variables, local variables, shared parameters(call by sharing) ;
Before executing the code, v8 will first convert the code into an abstract syntax tree through the Estree specification and then interpret, compile and execute it. In the abstract syntax tree (for abstract syntax trees, please see my other article), There is a scope, and memory reading is done by looking back through the identifier (variable naming) step by step. So if you need to share some memory between two methods, you can create it in their common scope.
In the client environment or node environment, we can implement multi-threading, and the two methods are similar (node passes worker_threads implementation, the browser implements it through Worker). The memory sharing here is mainly achieved with the help of the memory operation API (SharedArrayBuffer). Let’s first look at the example of browser implementation:
// 主线程 const buffer = new SharedArrayBuffer(1024) const typedArr = new Int16Array(buffer) const newWorker = new Worker('./worker.js') typedArr[0] = 20 newWorker.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
Because the memory cannot read each other after the process is started (the system level restrictions), memory sharing between processes is actually achieved by opening up a new section of shared memory. However, node does not support shared memory for the time being, and can only be implemented through low-level languages, for example: the shared-memory-disruptor addon plug-in implemented in c (described in another article).
Socket is divided into two implementations:
1. TCP Socket;
2. UNIX Domain Socket;
The main differences between the two The difference is as follows:
TCP Socket适用于单机,C/S架构等.但UNIX Domain Socket只适用于单机。 UNIX Domain Socket不需要经过一系列的网络中转(协议,分包,校验等等),性能更高,稳定性更好。
Concept: TCP Socket is the intermediate abstraction layer for communication between the application layer and the TCP/IP protocol family, and is provided by an operating system Inter-process communication mechanism;
TCP Socket communication should be one of the most common communication methods in our daily development (C/S architecture). The most common in our daily development are various application layer protocols (http , websocket, rpc, ftp, etc.), the http module in node is also implemented based on the net module.
Note: In fact, UDP also belongs to TCP layering (not strictly referring to TCP communication, but the TCP/IP layer in the network communication layer). Node provides the 'dgram' module to implement it, but in practice I haven’t been exposed to it in the application, so I don’t know much about it.
In node, TCP Socket is implemented by the net module. The net module mainly provides the following functions:
1. Upper layer IPC support (actually the implementation of pipeline communication, pipeline communication will be explained in detail later);
2, net.Server class;
// 服务端通过net.createServer创建服务,会返回net.Server对象,可以通过返回值进行各种事件监听,端口监听 const net = require('net') net.createServer((server => { server.end(`hello world!\n`) })).listen(3302, () => { console.log(`running ...`) })
3, net.Socket class;
const net = require('net') const socket = net.createConnection({port: 3302}) socket.on('data', data => { console.log(data.toString()) })
UNIX Domain Socket creates a file descriptor, and communication between different processes is carried out by reading and writing this file descriptor (can be divided into creating processes and other processes, and other processes can communicate with each other by creating processes as relays). 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
Pipeline communication is divided into two types, non-named pipes and named pipes.
The implementation of non-named pipes is the same as UNIX Domain Socket, which communicates by creating file descriptors.
Named pipes communicate through fixed file descriptors:
"\\\\.\\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是操作系统在终止进程前给进程发送的信号。在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的内容可阅读我之前关于进程的文章。
一开始我以为是redis,各种MQ之类的基于TCP的消息队列。但其实是操作系统内的消息队列,node暂时没有提供相关的上层接口,需要更底层实现,e.g. svmq
更多node相关知识,请访问:nodejs 教程!!
The above is the detailed content of Detailed explanation of several implementation methods of process communication in node. For more information, please follow other related articles on the PHP Chinese website!