Socket.io:如何使用 Socket.io-redis 适配器计算房间内的客户端数

Socket.io: How to count clients in a room with Socket.io-redis adapter

我开始使用 Socket.io with multiple nodes. It uses Socket.io-redis to connect all servers together and rooms 来构建聊天服务器来进行消息传递。

当客户端连接到服务器时,我将客户端加入某个房间。

io.on('connection', function(socket){
  socket.join("CLIENT_1");
});

所以我想获得连接到房间 "CLIENT_1"

的客户端数量
io.sockets.adapter.rooms["CLIENT_1"];

但我只能从当前进程获得连接。我怎样才能从所有通过 redis 适配器连接的服务器进程获得连接?

我已经完成了这个问题:

How to check socket is alive (connected) in socket.io with multiple nodes and socket.io-redis

但这对我没有帮助。

感谢提前。

撰写本文时:

redis adapter extends the base adapter,但它只有overrides/adds以下属性:

  • onmessage
  • broadcast
  • add
  • del
  • delAll

使用您的代码:

io.sockets.adapter.rooms["CLIENT_1"];

您正在查询 the rooms property这并没有被 redis 适配器覆盖,所以你实际上是在查询基本适配器,它只知道当前进程中的 rooms/clients。

为什么 redis 适配器没有覆盖 rooms 属性?因为为了匹配上面的调用签名,所以每次访问 属性 时,它都必须查询 redis 实例以构造一个包含所有房间和连接的对象 。不好。 (除非您能在查询对象值时弄清楚如何计算对象值。)

如果您想获取集群中所有进程与 "CLIENT_1" 房间的连接数,您必须使用如下方法将该功能添加到 the adapter itself

/**
   * Count the number of connections in a room.
   *
   * @param {String} room id
   * @param {Function} callback (optional)
   * @api public
   */

  Redis.prototype.numClients = function(room, fn){ ... }

您将在其中查询 redis 数据库实例。

IMO,这应该是所有其他适配器实现的基本适配器接口的一部分。 It's a common problem.

另一种方法是使用套接字中的customRequest/customHook方法。io-redis 3.1.0。我试过了,它有效。详情在这里。 https://github.com/socketio/socket.io-redis/issues/137

此方法非常有效:

io.sockets.adapter.clients(["room1"], function(err, clients){
  console.log("total clients in room1: %d", clients.length);
})

在版本 7.0.0 中,可以通过在房间上调用 allSockets 来实现。返回集的大小是集群中所有服务器上连接到您的房间的套接字数。

io.in("CLIENT_1").allSockets().then(sockets => {
  console.log("Number of clients", sockets.size)
});