生产中的 NodeJS 和 Socket.io:处理状态
Posted
技术标签:
【中文标题】生产中的 NodeJS 和 Socket.io:处理状态【英文标题】:NodeJS and Socket.io in production: Dealing with state 【发布时间】:2018-09-21 11:29:07 【问题描述】:在开发环境中,我有一个 nodejs 进程,它让 socket.io 在给定端口上侦听。客户端连接后,需要维护一个状态。 nodejs 脚本对文件进行一些处理,并通过套接字发送处理状态。这就像一个可能永远不会结束的批次。
如果客户端关闭浏览器然后再次打开(在开发环境中),网页只是再次连接到套接字并获取进程的当前状态,该进程将在后台处理文件处理特定用户。
为了让每个用户拥有一个进程并确保用户始终重新连接到他们在同一个端口上启动的同一个进程,我需要管理这些进程,每个用户一个作为服务器上的服务并预订每个用户的端口。
我将如何将此场景构建为单个 nodejs 入口点,该入口点可能会使用 nginx、PM2 和/或 Nodejs 集群来分叉进程并相应地路由套接字连接。换句话说,在这样的场景中,哪种架构最适合生产?
关于状态问题:
我持有的状态不仅仅是变量,它可以存储在数据库中。我有连续的文件读取流,这些流按照用户通过使用套接字连接到该进程的网页配置的顺序依次处理。此过程还连接到另一个套接字服务器到服务器,并且必须保持连接。
【问题讨论】:
【参考方案1】:我可能会将进程的 pid 暴露给路由脚本并使用会话和 cookie,将它们与分配给用户的 pid 一起保存到 Redis DB。
所以在连接时,您设置一个 cookie 和一个会话,可能为用户 ID 设置一个日期时间哈希(取决于您是否有与您的客户端关联的用户帐户),将其保存在用户 cookie 中并将 pid 保存在你的会话。
然后您可以将您的用户重定向到您的路由器中相应的进程分支。
编辑
我会使用 nodescript 作为代理。我找到了this 的答案,因为你没有发布代码我不知道你是如何创建你的流程的,所以我将它作为参考:
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
);
对于您的读取流,您可以在相应的工作人员中执行它们。 1 个 Worker 等于 1 个 socket.io 进程
【讨论】:
这会使用 Nginx 反向代理来完成吗?这个路由脚本怎么做?它是一个 nodejs 脚本,就像 Nginx revese 代理一样? @Valdir 据我所知,NginX 反向代理将客户端重定向到不同的服务和服务器。在这种情况下,您只需重定向到集群中的分叉。我用示例脚本更新了我的答案,以便您更好地理解我的答案。 是的,好像是路径。【参考方案2】:不要将你的状态保存在内存中。保存在数据库中(redis 是一个很好的数据库,因为它基于内存且速度超快),然后您不必担心套接字是否重新连接到同一个进程甚至是同一个服务器(如果您有多个服务器负载-余额)。
【讨论】:
我需要连接到同一个进程,因为我需要能够播放/暂停/修改将在该特定进程上为该用户运行的批处理进程。以上是关于生产中的 NodeJS 和 Socket.io:处理状态的主要内容,如果未能解决你的问题,请参考以下文章