我正在编写一个nodejs / socket.io应用程序,该应用程序使用AWS Elasticache中的集群和Redis作为RedisStore后端。该应用程序在房间周围很重要,我很难理解为什么只有Mobile Safari(iPad mini retina iOS7)在发出请求后才能离开它订阅的房间。即使从客户端关闭连接也会使插槽在服务器上保持嗡嗡声,并且对房间的订阅完好无损,但其他浏览器可以毫无问题地退出。
现在,在我的代码中,我一直在使用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 }
我在套接字编程方面相当新,所以我确定我遗漏了一些显而易见的东西,但是有没有人遇到过与移动网页套件类似的问题?
答案 0 :(得分:0)
所以我发现通过使用我自己的引用计数方法,我可以绕过需要socket.io来准确。由于我已经使用Redis通过pubsub支持我的套接字,我只是创建另一个客户端连接到redis和setex socket.id的到期。当我的套接字取消订阅或断开连接时,我删除了与socket.id相关联的Redis中的所有密钥。这样,我有一个即时快照,如果由于某种原因密钥在断开/取消删除时没有被删除,它将根据我为setex呼叫设置的内容到期。
我会记得两天后回来将我自己的答案标记为正确。