• Node 进程间怎么通信的


    我们都知道 Node 没法操作线程,但可以操作进程,一旦涉及主从模式的进程守护,或者是多机部署的需要,那么都可能碰上需要相互通信的场景,本篇就介绍几种常用方法。

    Node 原生 IPC(Inter-Process Communication,进程间通信)支持

    最自然的方式,比上一种“正规”一些,具有同样的局限性。其底层是 libuv。

    // parent.js
    const cp = require('child_process');
    const n = cp.fork(`child.js`);
    
    n.on('message', (m) => {
      console.log('父进程收到消息', m);
    });
    
    // 使子进程输出: 子进程收到消息 { hello: 'world' }
    n.send({ hello: 'world' });
    

    // child.js
    process.on('message', (m) => {
      console.log('子进程收到消息', m);
    });
    
    // 使父进程输出: 父进程收到消息 { foo: 'bar', baz: null }
    process.send({ foo: 'bar', baz: NaN });
    

    运行

    > node parent.js
    子进程收到消息 { hello: 'world' }
    父进程收到消息 { foo: 'bar', baz: null }
    

    libuv 的进程通信能力是怎么来的?

    这就要涉及到操作系统的进程间通信方式了,参见深刻理解Linux进程间通信(IPC)。进程间通信一般通过共享内存的方式实现的,使得多个进程可以访问同一块内存空间,是最快的可用 IPC 形式。

    通过 sockets

    最通用的方式,借助网络完成进程通信,有良好的跨环境能力,但存在网络的性能损耗。

    // parent.js
    const { spawn } = require('child_process');
    const child = spawn('node', ['child'], {
      stdio: [null, null, null, 'pipe'],
    });
    child.stdio[3].on('data', data => {
      console.log('222', data.toString());
    });
    

    // child.js
    const net = require('net');
    const pipe = net.Socket({ fd: 3 });
    pipe.write('killme');
    

    运行

    > node parent.js
    222 killme
    

    消息队列

    最强大的方式,既然要通信,场景还复杂,不妨扩展出一层消息中间件,漂亮地解决各种通信问题.

    消息队列可以参见 Rabitmq

    或者使用 Redis 的订阅发布,见下例

    // parent.js
    
    const cp = require('child_process');
    const child = cp.fork(`child.js`);
    var Redis = require("ioredis");
    var redis = new Redis();
    var pub = new Redis();
    
    // 订阅 news 通道,
    redis.subscribe("news", function (err, count) {
      // `count` represents the number of channels we are currently subscribed to.
    
    });
    
    // 监听 message 事件。
    redis.on("message", function (channel, message) {
      // Receive message Hello world! from channel news
      // Receive message Hello again! from channel music
      console.log("Receive message %s from channel %s", message, channel);
    }
    

    // child.js
    var Redis = require("ioredis");
    var pub = new Redis();
    
    // 发布新消息
    pub.publish("news", "Hello world!");
    pub.publish("music", "Hello again!");
    
    

    总结

    单机使用则直接 Node 原生 IPC 最为省事,就如 EggJS 中 Master 进程与 Worker 进程的通信。

    但你的服务负载需要部署去了多台机器,笔者更建议使用消息队列的方式来相互通信,毕竟追踪多机的 websocket 链路,是挺头疼的一件事。

  • 相关阅读:
    面试官:你和队友之间选一个淘汰,你怎么选?
    Spring Boot 如何干掉 if else?
    坑爹的 Java 可变参数,把我整得够惨。。
    厉害了,程序员的高考试卷,你能拿几分?
    6个步骤,全方位掌握 Kafka
    程序员逛酒吧,喝酒不是主要的。。
    图解 Java 垃圾回收机制,写得非常好!
    冲上云霄,Dubbo Go!
    人工智能都能写Java了!这款插件让你编程更轻松
    说了多少遍,姿势要对!
  • 原文地址:https://www.cnblogs.com/everlose/p/12846737.html
Copyright © 2020-2023  润新知