PM2 可以与 Node.js net API 一起使用吗?

Will PM2 work with Node.js net API?

背景

我需要制作一个监听多个 TCP 连接的服务器应用程序。这个应用程序必须是轻量级的,TCP 连接将来自 GPS 设备(而不是来自浏览器,所以我不能使用 WebSockets 例如)。

研究

为了确保它能正确扩展到数千台设备,我需要充分利用所有机器的 CPU。根据我的研究,我发现了两种方法:

  1. 创建net server and use the native clusterAPINode.js提供
  2. 创建一个应用程序并使用 PM2 "fork" 它跨所有 CPU

据我了解,这些选项是相互排斥的。如果我选择选项1,则无法使用PM2,反之亦然。

问题

我的团队到处都使用 PM2,因此为了保持一致性,我也想使用 PM2。这里的问题是 PM2 与 Node.js 套接字应用程序有问题。例如,我知道要使用 socket.io 我们需要安装额外的模块( sticky-session )但是因为我使用的是原生 API 没有信息 关于我需要做什么调整。

使用本机 net API 我不知道 PM2 是否会在 CPU 之间平均分配连接,也不知道数据是否会在适当的时候发送给正确的工作人员来了。

代码

为了演示我的 objective 我使用 cluster 原生 Node.js API:

制作了一个小应用程序
const cluster = require("cluster");
const net = require("net");
const numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
    console.log(`Master ${process.pid} is running`);

    // Fork workers.
    for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on("exit", (worker, code, signal) => {
        console.log(`worker ${worker.process.pid} died`);
    });

} else {
    // Workers can share any TCP connection
    const server = net.createServer( connection => {
        console.log(`Client connected to ${process.pid}`);
        connection.on( "end", () => console.log( `Client disconnected from ${process.pid}` ) );
        connection.on( "data", data =>console.log(`${process.pid} received ${data.toString("ascii")}`) );
        connection.on( "close", () => console.log(`Client closed connection with ${process.pid}`) );
    } );

    server.listen( 8124, () => console.log(`Worker ${process.pid} Bound`) );

    console.log(`Worker ${process.pid} started`);
}

根据我对文档的了解,此服务器通过所有 CPU 平衡负载并重定向连接。

您可以使用 telnet 尝试此示例:telnet localhost 8124

问题

  1. PM2 可以实现这种行为吗?如果是这样如何(代码会是什么样子)?

回答

所以,这里的答案很棘手...

PM2 集群的工作原理

所以,PM2集群模式实际上使用了Node.js原生的API。这意味着使用来自 Node 的 netcluster 原生 APIs 几乎只是复制 PM2 已经完成的工作,除非您想以完全不同的方式进行。

PM2 集群能否与套接字一起正常工作?

如果您的应用程序是 stateless

PM2 将使用 cluster 功能正确缩放(我将其称为 "fork" 使用 PM2 的应用程序)。

如果不是,PM2不能保证什么。

http://pm2.keymetrics.io/docs/usage/cluster-mode/#statelessify-your-application

结论

是的,但您的应用需要是无状态的。
您需要保存套接字连接以及 Redis 或 MongoDB 或其他内容。