在群集模式下将NodeJS Express服务器与PM 2一起使用

因此,我将尽我所能尝试对此进行解释:

我编写了一个TCP服务器,该服务器使用net中的NodeJS从可穿戴设备(gps手镯类型)接收数据。 TCP服务器具有connections = {}属性,其中包含所有连接,如下所示:

  • 服务器接受连接
  • 设备发送握手数据包,其中包含device id
  • 套接字的存储方式为:connections[device_id] = socket

同一TCP服务器还具有express服务器,该服务器允许我使用JSON post:curl -XPOST https://localhost:8080/send/device_id -d '{"command": "test"}'

将数据直接发送到设备

服务器解析URL,然后使用connections[params.device_id].write()

写入套接字

使用pm2 start server.js时,一切正常。我能够跟踪设备,接受和发送数据等。

问题是,当我在群集模式下使用pm2 start -i 5 server.js启动服务器时,设备连接可以正常工作,但是express部分给了我麻烦。

例如:当我在80%的时间内使用curl -XPOST https://localhost:8080/send/device_id -d '{"command": "test"}'时,它将转到错误的server.js实例,因为有server.js的五个副本在运行,并且每个副本都有express服务器,并且由于PM2可以管理所有内容,因此我的请求将到达tcp服务器,其中给定的device_id在5次中有1次连接。以我的理解,PM2启动server.js的5个实例,并管理和平衡tcpexpress的连接。

所以,我的问题是,我应该如何处理?有没有办法告诉PM2将端口8080转发到集群中所有正在运行的实例?这样,我可以向所有实例发送单个命令,然后在实例中检查device_id是否已连接,并写入其套接字。

这可能吗?如果可以,这是个好主意吗?如果没有,那么正确的方法是什么?

希望我能解释

致谢

*编辑*

从最初的问题可能不清楚,但是有问题的socket是通过net.createServer函数传递的,例如

const net = require('net');
const PORT = 8181;
let connections = {}

const server = net.createServer((c) => {
  //... device id parse
  connections[device_id] = c;
});

server.listen(PORT,() => {
  console.log('Server started on',PORT);
});
jidan88 回答:在群集模式下将NodeJS Express服务器与PM 2一起使用

尚不清楚您是打算将所有服务器实例作为工作程序运行在同一服务器上,还是可能在多个节点上运行多个工作程序。

要更改的主要内容是实例中的状态存储。听起来好像您正在通过使用connections[params.device_id]之类的调用来为每个工作人员存储数据,但是如果这些集合存在于单个工作人员的内存中,则不会知道彼此的数据或所连接的其他套接字。

如果是这种情况,那么您需要将所有状态管理移至Redis这样的共享存储库。会话数据等也应移至中央存储库。最好对服务器进行架构设计,以使它们尽可能处于无状态,以便您可以根据需要启动尽可能多的服务器。

  

确保您的应用程序是无状态的,这意味着没有本地数据   存储在进程中,例如会话/ Websocket连接,   会话内存和相关。使用Redis,Mongo或其他数据库来   在进程之间共享状态。

Socket.io具有redis-adapter,可帮助促进socket.io实例之间的通信,以便它们知道套接字连接并有助于广播。

如果您在多台服务器上运行,则可能需要设置一些粘性会话,以便最少将您路由到同一台服务器。但是,如果上面建议了实现共享状态,那么这不是问题。如果这不可能,那么也许像express-sticky-cluster这样的软件包可能会有所帮助。

我自己的实现允许使用共享数据存储和Redis支持的适配器在多个节点上有多个工作线程,因此如果客户端重新连接到其他实例,这不会有任何不同。

希望有帮助!

更新 在PM2上甚至有一个guideline指定了这种确切的体系结构。

本文链接:https://www.f2er.com/2966649.html

大家都在问