首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >socket.io+redis+expressjs集群-获取请求中的套接字对象

socket.io+redis+expressjs集群-获取请求中的套接字对象
EN

Stack Overflow用户
提问于 2016-02-10 11:01:46
回答 2查看 1.3K关注 0票数 6

基于这个答案的问题:https://stackoverflow.com/a/18650183/4478897

我试图找到这个解决方案,但似乎没有任何事情能像我所需要的那样奏效。

expressjssocket.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上初始化的。

一些示例流:

  • 客户端连接到http://localhostworker 1处理此请求。
  • 加载页面后,客户端连接到socket.ioWorker 2处理此连接。
  • 客户端进行发布,worker 1worker X再次处理此请求。

在这种情况下,当客户机执行POST时,只有worker 2知道该客户机的socket对象。这将得到一个未定义的socket对象。

因此,问题是:

如何从任何socket对象中获取客户机worker对象,以便在expressjs request对象上重用它。

也许我的代码是错的,但几乎就像上面提到的答案的链接。

注记

  • 不想使用某种代理。
  • 不想迁移到其他库(表达式、套接字.)
  • 对不起我的英语:)

使用最新的nodejs,socket.io,高速公路,socket.io-redis,redis.版本

别犹豫,问点什么!

更新1

可能的解决方案,但仍然需要测试它。不知道这是否真的很好:解决方案。

  • 更新3:我自己的答案的工作代码

更新2

像update 1但是使用message

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-24 22:42:50

嗯,最后尝试了这段代码,它起作用了(有一些拼写错误、修改和其他的东西),但是我确信这需要一个更好的代码。所以我愿意接受更多的答案!

当授权客户端套接字和其他东西时,这段代码是我的socket.io模块的一部分.

代码语言:javascript
复制
  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中即可。

代码语言:javascript
复制
// 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!');
});
票数 -1
EN

Stack Overflow用户

发布于 2017-01-11 06:55:33

在socket.io-redis 3.0.0中添加了remoteJoinremoteLeave方法

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35313377

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档