Nodejs每日一讲之Nodejs的进程间通信

网络 通信技术
linux系统提供了很多种进程间通信的方式,那么为什么nodejs选择unix域的,因为unix域相比其他进程间通信方式,有一个独特的优势,那就是传递文件描述符。

[[376460]]

本文转载自微信公众号「编程杂技 」,作者theanarkh。转载本文请联系编程杂技 众号。   

之前提了一个问题:nodejs中如何实现兄弟进程间的通信,大家分别列举了redis、ZooKeeper,MessageChannel,还有linux操作系统提供的共享内存等一系列的进程间通信方式。所以今天来分享一下到底如何实现nodejs的进程间通信。这里的讨论只限于linux系统,本机的进程。情况分为两种:父子进程,兄弟进程。

在nodejs中,实现进程间通信的方式其实只有一种,那就是unix域。linux系统提供了很多种进程间通信的方式,那么为什么nodejs选择unix域的,因为unix域相比其他进程间通信方式,有一个独特的优势,那就是传递文件描述符。unix域的实现是基于c/s模式的,类似tcp,udp。首先需要启动一个unix域服务器,然后各个unix客户端就可以"连接"这个服务器进行通信。

 

而在nodejs中父子进程的通信,底层使用的是socketpair,socketpair底层是也是unix域,不过他不是基于c/s模式的,如下图所示。

 

那么nodejs中,兄弟进程是如何通信的呢?最简单的方式就是通过主进程

 

但是这里多了一次中转,很明显效率上面会存着一些问题(相对直达和多一次中转,性能比较是很明显的,但是没具体测过。而且据说egg就是这么搞的,有了解的同学可以交流一下)。所以我们一般通过unix域实现兄弟进程的通信,但是我们需要做的事情就比较多了。我们看看unix域的类型。Unix域支持两种数据模式

1 流式( SOCK_STREAM),类似tcp,数据为字节流,需要应用层处理粘包问题。

 

2 数据报模式( SOCK_DGRAM ),类似udp,不需要处理数据边界。

 

但是不巧的是Nodejs使用的是流式模式,所以问题就变得复杂。这时候我们通过c/s模式虽然可以实现兄弟进程间的通信,但是我们拿到的数据可能是"乱的",这时候为什么呢?一般情况下,客户端给服务器发送1个字节,然后服务器处理,如果是基于这种场景,那么数据就不会是乱的。因为每次就是一个需要处理的数据单位。但是如果客户端给服务器发送1个字节,服务器还没来得及处理,客户端又发送了一个字节,那么这时候服务器再处理的时候,就会有问题。因为两个字节混一起了。就好比在一个tcp连接上先后发送两个http请求一样,如果服务器没有办法判断两个请求的数据边界,那么处理就会有问题。

我们写一个测试的例子。

unix域服务器

const net = require('net');net.createServer((client) => { client.on('data', (data) => { console.log(data.toString('utf-8')) })}).listen('\\\\?\\pipe\\ipc')

unix域客户端

const net = require('net');const socket = net.connect({path: '\\\\?\\pipe\\ipc'});setInterval(() => { socket.write('1'); socket.write('2');},1000)

我们看一下输出

 

我们看到输出可能是1然后2。也可能是12。在tcp协议中,这叫做粘包。那么我们如何解决这个问题呢?我们可以定义一个应用层协议。类似http协议一样,有了协议我们就知道,如何去解析收到的数据。接着我们还需要实现这个协议的解析器和封包逻辑,做完这些,我们就可以实现兄弟进程的通信了。

 

 

具体可参考ipc库的实现https://github.com/theanarkh/nodejs-ipc

 

责任编辑:武晓燕 来源: 编程杂技
相关推荐

2020-11-04 07:17:42

Nodejs通信进程

2017-08-06 00:05:18

进程通信开发

2010-01-05 10:00:48

Linux进程间通信

2019-08-30 10:08:33

NodejsJava语言

2022-05-24 08:09:00

HadoopHiveSpark

2011-06-22 17:09:50

QT 进程 通信

2022-10-11 15:18:41

NodeJSCookie

2012-05-04 13:25:46

HTML5

2019-05-08 11:10:05

Linux进程语言

2018-05-30 13:58:02

Linux进程通信

2022-01-17 07:59:13

SpringSpringMVCSpringBoot

2017-06-19 13:36:12

Linux进程消息队列

2018-01-12 14:35:00

Linux进程共享内存

2013-03-28 13:14:45

AIDL进程间通信Android使用AI

2016-05-24 10:40:32

NodeJS总结

2019-11-27 10:36:11

进程通信IPC

2022-07-04 08:29:13

electron通信

2020-09-10 09:05:29

UDP服务器Nodejs

2019-11-08 14:47:49

TCPIP网络

2017-08-07 20:18:11

Android线程handler
点赞
收藏

51CTO技术栈公众号