zoukankan      html  css  js  c++  java
  • 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 链路,是挺头疼的一件事。

  • 相关阅读:
    一些话
    把视频文件拆成图片保存在沙盒中
    相册视频保存进沙盒
    数据库
    C 计算数组长度
    iOS之与JS交互通信
    iOS之duplicate symbols for architecture x86_64错误
    iOS之隐藏状态栏
    iOS之开发程序之间的跳转及跳转到appStore
    iOS之常用的判NULL的方法
  • 原文地址:https://www.cnblogs.com/everlose/p/12846737.html
Copyright © 2011-2022 走看看