在节点集群之间存储Javascript Map

问题描述

我目前在Javascript Map中保存对套接字的引用。我需要使此映射对所有集群上运行的节点的实例都可访问,以便始终获得与用户关联的socket.id。在我的应用程序模块中:

var socketMap = new Map()

// socket.io events
io.on( "connection",function( socket )
{
  if (socket.request.session.authenticated_user) {
    console.log( "A user connected" );
    socketMap.set(socket.request.session.authenticated_user.toString(),socket.id);

    socket.on( "disconnect",function() {
      console.log( "A user disconnected" );
      socketMap.delete(socket.request.session.authenticated_user);
    });
  }
});

var emit_to_socket = function (user_id,message) {

  if (socketMap.has(user_id.toString())) {
    if (socketMap.get(user_id.toString())) {
      io.to(socketMap.get(user_id.toString())).emit('message',message);
    }
  }
};

exports.emit_to_socket = emit_to_socket;

解决方法

我需要使此映射对所有集群上运行的节点的实例都可访问,以便始终获得与用户关联的socket.id。

如果需要与所有群集共享数据,则不能使用Javascript内存对象,例如Map对象。相反,您将需要使用可以在多个进程(您的集群进程)之间共享的东西。常见的解决方案是使用Redis(在内存数据库中),然后所有群集进程都可以访问它们。 Redis具有使您能够执行类似于Map对象的功能的功能。

实际上,socket.io的群集版本已为此目的使用了redis,因此它可以跟踪所有房间以及所有群集中的所有已连接用户,并且任何群集都可以广播到任何房间或发送到任何套接字,而无论他们连接到哪个集群。

或者,您可以让主进程保留Map对象,然后集群中的每个其他进程都必须通过进程间通信与主集群进行通信,以从单个Map对象中获取或设置某些内容(本质上是穷人的Redis出于单一目的)。