【问题标题】:Scaling socket.io between servers在服务器之间扩展 socket.io
【发布时间】:2012-04-11 05:01:33
【问题描述】:

扩展 socket.io 应用程序的方法有哪些?我看到以下我不明白如何解决的问题:

  • 缩放的 socket.io 应用程序如何向房间广播?换句话说,socket.io 怎么知道其他服务器的邻居?

我很难想象它应该如何工作——也许是所有必要信息的共享变体存储,例如 redis——这可能吗?

编辑:我发现这篇文章:http://www.ranu.com.ar/2011/11/redisstore-and-rooms-with-socketio.html

据此,我做了以下工作:

   var pub = redis.createClient();  
   var sub = redis.createClient();
   var store = redis.createClient();
   pub.auth("pass");
   sub.auth("pass");
   store.auth("pass");

    io.configure( function(){
io.enable('browser client minification');  // send minified client
io.enable('browser client etag');          // apply etag caching logic based on version number
    io.enable('browser client gzip');          // gzip the file
io.set('log level', 1);                    // reduce logging
io.set('transports', [                     // enable all transports (optional if you want flashsocket)
    'websocket'
  , 'flashsocket'
  , 'htmlfile'
  , 'xhr-polling'
  , 'jsonp-polling'
]);
var RedisStore = require('socket.io/lib/stores/redis');
io.set('store', new RedisStore({redisPub:pub, redisSub:sub, redisClient:store}));
    });

但我收到以下错误:

      Error: Uncaught, unspecified 'error' event.
     at RedisClient.emit (events.js:50:15)
     at Command.callback (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:232:29)
     at RedisClient.return_error (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:382:25)
     at RedisReplyParser.<anonymous> (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:78:14)
     at RedisReplyParser.emit (events.js:67:17)
     at RedisReplyParser.send_error (    /home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js:265:14)
     at RedisReplyParser.execute (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js:124:22)
     at RedisClient.on_data (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:358:27)
     at Socket.<anonymous> (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:93:14)
     at Socket.emit (events.js:67:17)

我的 Redis 凭据绝对正确。

编辑:很奇怪,但是禁用 Redis 授权后一切正常。所以这个问题仍然有效。另外,我有一个关于如何在此 RedisStorage 模式下获取组(房间)的所有参与者的信息(例如用户名)的问题,是否可以实现此功能?理想情况下,这可以通过 Redis Pub/Sub 功能完成。

【问题讨论】:

    标签: node.js socket.io


    【解决方案1】:

    您可以使用 socket.io 集群来实现这一点 https://github.com/muchmala/socket.io-cluster

    【讨论】:

      【解决方案2】:

      尝试添加此代码;

      pub.on('error', function (err) {
        console.error('pub', err.stack);
      });
      sub.on('error', function (err) {
        console.error('sub', err.stack);
      });
      store.on('error', function (err) {
        console.error('store', err.stack);
      });
      

      它不会修复它,但它至少应该给你一个更有用的错误。

      【讨论】:

        【解决方案3】:

        我建议你不要使用 RedisStore。它在 CPU 使用方面存在问题,因为它对 pub-sub 的使用不当导致不可扩展(它可以接收少于一个带有 socket.io 的纯 node.js 实例的负载,这是非常没用的)。我个人使用 Redis 作为数据存储来保存房间列表并实现我自己的房间功能(Redis 是内存中的键值数据库,但具有持久性机制)。当您需要房间数据时,只需从同一个 redis 中获取数据即可。但是,为了能够在多个实例中运行 Socket.io,您还需要像 HAProxy、Nginx 这样的负载均衡器将工作分离到多个 node.js 端口,否则,您的用户仍将只使用一个 node.js 进程。这是一项巨大的工作。如果您还有其他语言的其他 Web 前端,那么工作量也会更大,因为某些网络会阻止除端口 80 和 443 之外的所有端口。您可以在以下位置阅读有关这些内容的更多信息:

        http://book.mixu.net/node/ch13.html

        【讨论】:

          【解决方案4】:

          另一种可能的解决方案是使用PubNub 之类的替代方案来扩展实时交互。我在开发Mote.io 时遇到了类似的问题,并决定使用托管解决方案而不是构建负载均衡器。我现在为 PubNub 工作。

          PubNub 会处理您所说的数据同步问题。通常,您需要跨服务器同步 redis 或将您的客户端负载平衡到同一个实例,以确保它们获得所有相同的消息。 PubNub 对此进行了抽象,因此您无需担心。

          10 行代码的实时聊天应用

          Enter Chat and press enter
          <div><input id=input placeholder=you-chat-here /></div>
          
          Chat Output
          <div id=box></div>
          
          <script src=http://cdn.pubnub.com/pubnub.min.js></script>
          <script>(function(){
          var box = PUBNUB.$('box'), input = PUBNUB.$('input'), channel = 'chat';
          PUBNUB.subscribe({
              channel  : channel,
              callback : function(text) { box.innerHTML = (''+text).replace( /[<>]/g, '' ) + '<br>' + box.innerHTML }
          });
          PUBNUB.bind( 'keyup', input, function(e) {
              (e.keyCode || e.charCode) === 13 && PUBNUB.publish({
                  channel : channel, message : input.value, x : (input.value='')
              })
          } )
          })()</script>
          

          【讨论】:

            【解决方案5】:

            使用 RabbitMQ

            我使用 rabbitMQ 实现了socket.io 应用程序扩展。在我当前的设置中,我在 docker swarm 中运行 socket.io 应用程序容器的两个副本并与它们通信。以下是每条消息中显示的容器 ID 的演示:

            如何

            RabbitMQ 是一个消息代理,基本上,它同步应用程序后端的所有实例。后端的每个实例都将其消息推送到 rabbitMQ 上的队列,该队列被所有其他实例使用。 NodeJS 中的 RabbitMQ 处理程序如下所示。

            function rabbitHandler(io){
              rabbitMQHandler('amqp://test_rabbit', function(err, options){
            
                if(err){
                  throw err;  
                }
            
                options.onMessageReceived = onMessageReceived;
            
                io.on('connection', websocketConnect);
            
                function websocketConnect(socket){
            
                  console.log('New connection')
                  io.emit('start', {ipHost: os.hostname()})
            
                  socket.on('disconnect', socketDisconnect);
                  socket.on('message', socketMessage);
            
                  function socketDisconnect(e){
                    console.log('Disconnect ', e);
                  }
            
                  function socketMessage(text){
                    var message =  {text: text, date: new Date(), ip: os.hostname()};
              //      io.emit('message', message) // Instead of emitting the message on socket, it is being pushed on rabbitMQ queue.
                    options.emitMessage(message);
                  }
                }
            
                function onMessageReceived(message){
            
                  io.emit('message', message)
                }
            
              });
            } 
            

            套接字客户端没有任何变化。

            整个项目在以下链接中给出,带有 docker image 和 docker compose 文件。你可以去那里试试。

            https://github.com/saqibahmed515/chat-scaling

            【讨论】:

              猜你喜欢
              • 2015-08-29
              • 1970-01-01
              • 1970-01-01
              • 2018-12-29
              • 1970-01-01
              • 2014-01-17
              • 1970-01-01
              • 2021-11-21
              • 2018-10-27
              相关资源
              最近更新 更多