2012-03-27 41 views
5

扩展socket.io应用程序的方法是什么?我看到以下问题,我不明白如何解决:在服务器之间缩放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功能完成。

回答

0

尝试增加在此代码;

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); 
}); 

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

0

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

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

0

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

PubNub会照顾您正在讨论的数据同步问题。通常情况下,您需要在服务器之间同步Redis,或者将客户端负载平衡到同一实例,以确保它们获得所有相同的消息。 PubNub将这个摘要抽象出来,所以你不必担心它。

在代码

enter image description here

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> 
的10行即时聊天应用