基于这个答案的问题:https://stackoverflow.com/a/18650183/4478897
我试图找到这个解决方案,但似乎没有任何事情能像我所需要的那样奏效。
对expressjs和socket.io进行集群,我们可以使用redis共享会话,并在io世界中发送io消息(io.sockets.on('connection',.)。问题是如果我们想在socket.join/leave( expressjs world,route.get/post)中发送消息(或使用简单的route.get/post)。
如果我们不使用集群,我们可以将客户端socket对象访问到express request对象(或简单地将export设置为io对象),然后在任何GET/POST路由上随时使用它。
另一方面,如果我们要聚类并使用上述方法在expressjs世界中获取expressjs对象,有时socket对象是未定义的,因为该客户端的socket对象是在其他worker上初始化的。
一些示例流:
worker 1处理此请求。socket.io。Worker 2处理此连接。worker 1或worker X再次处理此请求。在这种情况下,当客户机执行POST时,只有worker 2知道该客户机的socket对象。这将得到一个未定义的socket对象。
因此,问题是:
如何从任何socket对象中获取客户机worker对象,以便在expressjs request对象上重用它。
也许我的代码是错的,但几乎就像上面提到的答案的链接。
注记
使用最新的nodejs,socket.io,高速公路,socket.io-redis,redis.版本
别犹豫,问点什么!
更新1
可能的解决方案,但仍然需要测试它。不知道这是否真的很好:解决方案。
更新2
像update 1但是使用message
发布于 2016-02-24 22:42:50
嗯,最后尝试了这段代码,它起作用了(有一些拼写错误、修改和其他的东西),但是我确信这需要一个更好的代码。所以我愿意接受更多的答案!
当授权客户端套接字和其他东西时,这段代码是我的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!');
});发布于 2017-01-11 06:55:33
在socket.io-redis 3.0.0中添加了remoteJoin和remoteLeave方法
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。
https://stackoverflow.com/questions/35313377
复制相似问题