提问者:小点点

生产中的NodeJS和Socket.IO:处理状态


在开发环境中,我有一个单一的nodejs进程,它在给定的端口上侦听socket.io。一旦客户端连接,就需要维护一个状态。nodejs脚本在文件上执行一些工作,并通过套接字发送处理的状态。就像一批可能永远不会结束的东西。

如果客户机关闭浏览器,然后再次打开(在开发环境中),web页面只需再次连接到套接字并获取进程的当前状态,该进程将在后台为特定用户处理文件。

为了使每个用户都有一个进程,并确保用户总是在同一个端口上重新连接到他们启动的同一个进程,我需要管理这些进程,每个用户一个进程作为服务器上的服务,并为每个用户预订端口。

我如何将此场景构建为单个nodejs入口点,该入口点可能使用Nginx,PM2和或nodejs集群来分叉进程并相应地路由套接字连接。换句话说,在这样的场景中,哪一个是生产的最佳架构?

关于状态问题:

我持有的状态不是简单的变量,可以存储在数据库中。我有连续的文件读取流,它们按照用户通过使用套接字连接到该进程的web页面配置的顺序一个接一个地进行处理。这个进程还连接到另一个socket服务器到服务器,并且必须保持连接。


共2个答案

匿名用户

我可能会将进程的pid公开给路由脚本,并使用会话和cookie,将它们与分配给用户的pid一起保存到Redis DB中。

因此,在连接时,您设置一个cookie和一个会话,可能使用用户ID的datetime-hash(取决于您是否有与客户机相关联的用户帐户),将其保存在用户cookie中,并将pid保存在会话中。

然后可以将用户重定向到路由器中进程的相应分叉。

编辑

我会用nodescript作为代理。我找到了这个答案,因为您没有发布代码,所以我不知道您是如何创建流程的,所以我将使用它作为参考:

const socketio = require('socket.io');
const redis = require('redis');

on.connect((req, res) => {
    let uid,
        pid,
        port;

    // if user does not have the cookie yet
    if (!req.cookies.uid) {
        uid = getNewUserID(req); // create uid from information from the request, set a cookie later
        pid = createWorker(uid); // generate new socket.io worker in cluster and return pid
        port = getSocketPort(pid); // get socket port from worker

        // save acquired variables to database
        redis.set(uid, [pid, port], function(err, reply) {
            if (err) throw err;
            console.log(reply);
        });
    };

    uid = req.cookies.uid; // get uid from request
    pid = getPid(uid); // get pid from redis

    socketio(getSocketPort(pid)); // connect client to port of correct worker
});

对于您的readstreams,您可以在相应的worker中执行它们。1个Worker等于1个socket.io进程

匿名用户

不要在内存中保存您的状态。保存在db中(redis是一个很好的db,因为它基于内存并且速度非常快),然后您不必担心套接字是否重新连接到相同的进程,甚至是相同的服务器(如果您有多个具有负载平衡的服务器)。