基于这个答案的问题:https://stackoverflow.com/a/18650183/4478897
我试图找到这个解决方案,但似乎没有任何方法可以按照我需要的方式工作。
群集expressjs
和socket.io
我们可以使用redis共享会话,并在io
世界(io
...)内发送io.sockets.on('connection',
条消息。问题是我们是想在socket.join/leave
世界(expressjs
)内发送消息(或使用简单的route.get/post
)。
如果我们不使用群集,我们可以将客户端socket
对象提升到快速request
对象(或简称export
io
对象),然后在任何GET / POST路线上的任何时间。
另一方面,如果我们进行聚类并使用上述方法在socket
世界中获取expressjs
对象,有时socket
对象未定义,因为{{1该客户端的对象在其他socket
初始化。
一些示例流程:
worker
处理此请求。worker 1
。 socket.io
处理此连接。Worker 2
或worker 1
处理此请求。在这种情况下,当客户端执行POST时,只有worker X
知道此客户端的worker 2
对象。所以这会得到一个未定义的socket
对象。
所以,问题是:
我们如何从任何socket
获取客户端socket
对象,以便在worker
对象上重用它。
也许我的代码错了,但几乎就像上面提到的答案的链接。
注释
使用最后一个nodejs,socket.io,expressjs,socket.io-redis,redis ......版本
不要犹豫,不要问问题!
更新1
可能的解决方案但仍需要测试它。不知道这是否真的很好:解决方案。
更新2
与更新1类似,但使用https://nodejs.org/dist/latest-v5.x/docs/api/cluster.html#cluster_event_message
答案 0 :(得分:1)
remoteJoin
中添加了 remoteLeave
和3.0.0
方法:
io.adapter.remoteJoin('<my-id>', 'room1', function (err) {
if (err) { /* unknown id */ }
// success
});
io.adapter.remoteLeave('<my-id>', 'room1', function (err) {
if (err) { /* unknown id */ }
// success
});
注意:实现看起来很多(希望如此?),如答案above。
答案 1 :(得分:-1)
最后尝试了代码并且它可以工作(有一些错误的修改和其他东西),但我确信需要在某处更好的代码。所以我愿意接受更多答案!
当授权客户端套接字和其他一些东西时,此代码是我的socket.io模块的一部分......
var redis = require("redis");
var redisPub = redis.createClient();
var redisSub = redis.createClient();
var PubSubChannel = "clusterChannel";
// Function that checks if this worker knows the socket object of this socketId.
// If not, publish the message to all the other sockets (workers)
io.socketDo = function (type, socketId, roomName) {
if (typeof io.sockets.connected[socketId] != "undefined") {
if (type === "join") {
return io.sockets.connected[socketId].join(roomName);
}
if (type === "leave") {
return io.sockets.connected[socketId].leave(roomName);
}
} else {
redisPub.publish(
PubSubChannel,
JSON.stringify({
type: type,
socketId: '' + socketId,
roomName: roomName
})
);
}
};
// Subscribe to some channel
redisSub.subscribe(PubSubChannel);
// When this worker receive a message from channel "PubSubChannel" checks
// if it have the socket object for this socketId and do the operation
redisSub.on("message", function (channel, data) {
data = JSON.parse(data);
var type = data.type;
var socketId = data.socketId;
var roomName = data.roomName;
if ((type === "join" || type === "leave") && channel == PubSubChannel){
if (typeof io.sockets.connected[socketId] != "undefined") {
if (type === "join") {
return io.sockets.connected[socketId].join(roomName);
}
if (type === "leave") {
return io.sockets.connected[socketId].leave(roomName);
}
}
}
});
然后只需导出模块并将其附加到您的快递request => req.io = io
// req.session.socketId value is fetched on "io.sockets.on('connection', function(socket) {"
// by express to socket.io using redis shared sessions
app.get('/', function (req, res) {
req.io.socketDo('join', req.session.socketId, 'someRoomToJoin');
// IT WORKS!
req.io.sockets.in('someRoomToJoin').emit('text');
req.io.socketDo('leave', req.session.socketId, 'someRoomToLeave');
res.send('Hello World!');
});