Nodejs实时交互应用架构——进程间高效通信方式问题

Nodejs实时交互应用架构——进程间高效通信方式问题

最近在使用socket.io开发一个实时交互应用,遇到一个问题:

1、socket.io所在的nodejs进程,由于需要负责与所有的client进行通信、心跳,再加上要做游戏内部的逻辑处理,所以占用了主线程cpu,并发连接数上不去

现在想把架构修改一下: 1、Nodejs工作进程(水平扩展) 负责与client通信、广播消息、心跳等,不处理业务逻辑。收到请求后,把请求转发给逻辑处理进程来进行业务处理

2、逻辑处理进程 负责内存中保存业务数据,接收工作进程的消息,进行逻辑处理,并把处理结果返回。

现在的问题是,如何实现这2种进程之间的通信比较好。 1、据我所知,node只提供了主、子进程之间的通信api,且写起来很麻烦 2、一种方法是工作进程和逻辑处理进程都作为一个http服务器存在,互相之间通过http通信,但感觉这种方式好像比较‘重‘

请教高手有没有好的办法


7 回复

针对您提到的Node.js实时交互应用架构中的进程间高效通信问题,我们可以采用child_process模块来创建子进程,并利用IPC(Inter-Process Communication)机制来进行高效的进程间通信。此外,也可以考虑使用更高级的库如cluster或第三方库如bullet来简化进程管理和通信。

示例代码

1. 工作进程(Worker Process)

const { fork } = require('child_process');
const net = require('net');

// 创建一个TCP服务器,用于接收客户端的连接
const server = net.createServer((client) => {
    client.on('data', (data) => {
        // 将接收到的数据发送到逻辑处理进程
        logicProcess.send({ type: 'request', data });
    });
});

server.listen(3000, () => {
    console.log('Worker listening on port 3000');
});

// 创建逻辑处理进程
const logicProcess = fork('./logic-process.js');

2. 逻辑处理进程(Logic Process)

process.on('message', (msg) => {
    if (msg.type === 'request') {
        // 这里模拟业务逻辑处理
        const result = processRequest(msg.data);

        // 将处理结果返回给工作进程
        process.send({ type: 'response', data: result });
    }
});

function processRequest(data) {
    // 模拟一些业务逻辑处理
    return `Processed ${data}`;
}

解释

  • 工作进程:监听客户端的连接,一旦有新的数据到达,就通过process.send()将数据发送给逻辑处理进程。
  • 逻辑处理进程:监听来自工作进程的消息,处理这些消息并返回处理结果。处理结果通过process.send()返回给工作进程。

这种方法利用了Node.js内置的IPC机制,可以实现轻量级的进程间通信。相比HTTP通信,这种方式更加简洁和高效。

其他方案

除了上述方法,还可以考虑使用消息队列(如RabbitMQ、Kafka)来实现进程间的异步通信,这样可以更好地解耦各组件,提高系统的可扩展性和稳定性。


我做的一个项目中,是用socket进行服务通信,主要是考虑到服务可以异地部署,数据格式定义也要容易些。看了一篇文章,三种进程间通信方式,匿名管道、共享内存、套接字,其中匿名管道效率是最高的,Node的子进程通信应该也是采用这种方式吧

感谢,可以给个文章地址么。那你们的项目中是自己写socket,定义消息的格式来做的么

可以起多个node进程啊(cluster)

可以多子进程处理,通信可以通过主进程的事件来触发和广播。

其实这是nodejs进程间通信协议的选择,考虑到以后的扩展性、分布式部署、简单易用等特点,socket.io长连接挺好。如果想提高效率,就用原生的socket协议吧。

为了实现Node.js进程中高效的通信,可以考虑使用IPC(进程间通信)机制,比如child_process模块中的IPC通信。此外,还可以使用第三方库如cluster模块来实现多进程管理,或者使用Redis作为消息队列来解耦各个进程间的通信。

这里提供一个基于child_process模块的简单示例:

示例代码

工作进程 (worker.js)

const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
    // 创建一个新的Worker线程
    const worker = new Worker(__filename);
    worker.postMessage({ action: 'connect', client: { id: 'client-1' } });
} else {
    // 接收来自主进程的消息
    parentPort.on('message', async (msg) => {
        if (msg.action === 'connect') {
            console.log(`Connected to client ${msg.client.id}`);
            // 向主进程发送消息
            parentPort.postMessage({ action: 'sendToLogic', data: 'some data' });
        }
    });
}

逻辑处理进程 (logic.js)

const { Worker, isMainThread, parentPort } = require('worker_threads');

if (isMainThread) {
    // 创建一个新的Worker线程
    const worker = new Worker(__filename);
    worker.postMessage({ action: 'processData', data: 'some data' });
} else {
    // 接收来自主进程的消息
    parentPort.on('message', async (msg) => {
        if (msg.action === 'processData') {
            console.log(`Processing data ${msg.data}`);
            // 处理完成后,向主进程发送消息
            parentPort.postMessage({ action: 'dataProcessed', result: 'processed data' });
        }
    });
}

解释

  1. 工作进程:主要负责与客户端的通信,它创建一个子线程(逻辑处理进程),并传递必要的数据。当需要执行业务逻辑时,它会将任务发送给子线程。

  2. 逻辑处理进程:主要负责处理业务逻辑,它接收来自工作进程的数据,并在处理完成后返回结果。

  3. 使用parentPort.postMessage()parentPort.on('message')来实现进程间的通信。这种方法比HTTP通信更轻量级,且更容易集成到现有的Node.js项目中。

这种方法可以有效地将工作进程和逻辑处理进程解耦,提高系统的可扩展性和响应速度。

回到顶部