0

我正在编写一个 nodejs/socket.io 应用程序,它使用 AWS Elasticache 中的集群和 Redis 作为 RedisStore 后端。该应用程序在房间周围大量工作,我很难理解为什么只有 Mobile Safari(iPad mini Retina iOS7)在发出请求后不能离开它订阅的房间。即使从客户端关闭连接也会使套接字在服务器上嗡嗡作响,并且对房间的订阅完好无损,但其他浏览器可以毫无问题地退出。

  1. NodeJS v0.10.25
  2. Socket.io v0.9.16
  3. Redis v2.8.6 (AWS Elasticache)
  4. Ubuntu 14.04 LTS(TCP 模式下负载均衡器后面的 EC2)

现在,在我的代码中,我一直在使用该io.sockets.manager.roomClients对象来遍历并查看哪些房间实际在使用中。这是因为io.sockets.clients()在连接打开和关闭一段时间后报告的数据完全不准确。

我的代码真的太长了,不能放在这里,而且相当私密,但这基本上是我所拥有的:

服务器:

if (cluster.isMaster) {

    function heartbeat(){
        // io.sockets.clients() doesn't splice dropped connections off the array
        // so we have to use io.sockets.manager.roomClients to see active rooms
        for( var i in io.sockets.manager.roomClients ) {
            console.log("Client:", i, io.sockets.manager.roomClients[i] );
        }
        setTimeout(heartbeat,5000);
    }

    heartbeat();

} else {

    io.sockets.on('connection', function (socket) {

        socket.on('subscribe', function (room) {
            console.log("Starting:",room);
            socket.join(room);
        });

        socket.on('unsubscribe', function (room) {
            console.log("Leaving:",room);
            socket.leave(room);
        });

        socket.on('disconnect', function () {
            console.log("Close Shop");
        });

    });
}

客户端:

socket.emit('subscribe', 'some-room');

服务器日志

Starting: some-room

然后我得到Client每个超时滴答的日志:

Client: lhZsH1oL2vV7BML9QkSW { '': true, '/some-room': true }
Client: lhZsH1oL2vV7BML9QkSW { '': true, '/some-room': true }
Client: lhZsH1oL2vV7BML9QkSW { '': true, '/some-room': true }
Client: lhZsH1oL2vV7BML9QkSW { '': true, '/some-room': true }
Client: lhZsH1oL2vV7BML9QkSW { '': true, '/some-room': true }

现在,问题就在这里。如果我取消订阅或断开与桌面浏览器的连接:

socket.emit('unsubscribe', 'some-room');
Leaving: some-room

或者

socket.disconnect();
Close Shop

刻度线如下所示:

Client: lhZsH1oL2vV7BML9QkSW { '': true }

我希望如此,因为我们知道,socket.io 在连接清理方面很糟糕,但至少房间订阅已经消失了。但是,在我的平板电脑上,取消订阅或断开连接后,房间订阅仍保留在io.sockets.manager.roomClients对象中:

Client: lhZsH1oL2vV7BML9QkSW { '': true, '/some-room': true }

我在套接字编程方面相当新,所以我确定我遗漏了一些明显的东西,但是有没有人对移动 websockets 有类似的问题?

4

1 回答 1

0

所以我发现通过使用我自己的引用计数方法,我可以绕过需要 socket.io 来准确。由于我已经在使用 Redis 通过 pubsub 支持我的套接字,所以我只需创建另一个到 redis 的客户端连接,并在过期时设置 socket.id。当我的套接字取消订阅或断开连接时,我删除了 Redis 中与 socket.id 关联的所有键。这样,我就有了 whos 的即时快照,如果由于某种原因在断开/取消订阅时密钥没有被删除,它将根据我为 setex 调用设置的内容过期。

我会尽量记住两天后回来将我自己的答案标记为正确。

于 2014-05-19T07:06:59.280 回答