node-websocket-server:可以为单个node.js进程提供多个独立的"广播"吗?

S M*_*S M 57 websocket node.js

我想知道是否可以在同一个node-websocket-server应用程序实例上运行的不同websocket"连接"上进行广播.想象一下,聊天服务器有多个房间,只在单个node.js服务器进程上向每个房间的参与者广播消息.我已成功实现了每个进程一个聊天室的解决方案,但我希望将其提升到新的水平.

Shr*_*hna 53

你可能想尝试一下Push-it:http://github.com/aaronblohowiak/Push-It它建立在Socket.IO之上.设计符合Bayeux协议.

但是,如果您需要使用redis pubsub的东西,可以查看http://github.com/shripadk/Socket.IO-PubSub

特别回答您的问题:您可以维护连接到websocket服务器的所有客户端的数组.可能只是广播到这些客户的一部分?广播方法基本上是在幕后.node-websocket-server/Socket.IO维护所有连接的客户端的数组,并循环遍历所有客户端"发送"消息给每个客户端.代码要点:

// considering you storing all your clients in an array, should be doing this on connection:
clients.push(client)

// loop through that array to send to each client
Client.prototype.broadcast = function(msg, except) {
      for(var i in clients) {
          if(clients[i].sessionId !== except) {
             clients[i].send({message: msg});
          }
      }
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您只想将消息中继到特定频道,只需维护客户端订阅的所有频道的列表.这是一个简单的例子(让你开始):

clients.push(client);


Client.prototype.subscribe = function(channel) {
      this.channel = channel;
}

Client.prototype.unsubscribe = function(channel) {
     this.channel = null;
}

Client.prototype.publish = function(channel, msg) {
      for(var i in clients) {
         if(clients[i].channel === channel) {
            clients[i].send({message: msg});
         }
      }
}
Run Code Online (Sandbox Code Playgroud)

为了使它更容易使用EventEmitters.因此在node-websocket-server/Socket.IO中查看消息的接收位置并解析消息以检查类型(subscribe/unsubscribe/publish)并根据类型发出带有消息的事件.例:

Client.prototype._onMessage = function(message) {
       switch(message.type) {
         case 'subscribe':
             this.emit('subscribe', message.channel);
         case 'unsubscribe':
             this.emit('unsubscribe', message.channel);
         case 'publish':
             this.emit('publish', message.channel, message.data);
         default:

       }
}
Run Code Online (Sandbox Code Playgroud)

聆听应用程序中发出的事件('连接'):

client.on('subscribe', function(channel) {
     // do some checks here if u like
     client.subscribe(channel);
});
client.on('unsubscribe', function(channel) {
     client.unsubscribe(channel);
});
client.on('publish', function(channel, message) {
     client.publish(channel, message);
});
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • 这太棒了,非常感谢!如果我开始时只知道,我会从一开始就使用Socket.IO. (2认同)
  • 当然!很高兴我有所帮助:) (2认同)
  • 非常有帮助.谢谢! (2认同)
  • 只是将消息广播到所有频道和客户端是个好主意,那么我们会在浏览器上进行过滤吗? (2认同)

Sha*_*ean 25

我不确定在创建其他答案时房间是否是一个功能,但在文档中,它们具有您正在寻找的功能.所以转到该链接并搜索rooms.

以下是该网站的示例:

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.join('justin bieber fans');
  socket.broadcast.to('justin bieber fans').emit('new fan');
  io.sockets.in('rammstein fans').emit('new non-fan');
});
Run Code Online (Sandbox Code Playgroud)

基于其他答案,它更侧重于缩放,如果内置版本可以很好地扩展到建议的答案,我会喜欢一些见解.

  • 是的,房间不是那么的.我猜这个问题的低投票的原因是你创造了一个"justin beiber粉丝"的房间:P (10认同)

Sea*_*mbo 9

Shripad K的答案非常有条理.做得好.

我认为该解决方案会有一些扩展问题.

如果您在500个聊天室中拥有10,000个并发用户,那么每次任何用户发送消息时,您都必须遍历所有10,000个客户端.我怀疑在redis的结构中将客户列表存储在给定房间中会更快,只需获取此列表并发送给这些客户端.

1)不确定这是否真的更快.2)不确定什么可以存储在redis中,然后允许我们引用客户端.也许可能有服务器中所有客户端的哈希,通过唯一的ID和redis,我们可以只存储每个聊天室的一组用户ID?

这似乎更具可扩展性吗?

我已经编写了一个基于fzysqr的节点聊天服务器,并且需要在我们广泛推出之前使其可以扩展为多个聊天.

  • 好吧,如果您不进行负载平衡,则无法将请求代理到这些多个节点。所以你只有节点空闲,没有请求到达它们。 (2认同)