我应该使用什么? Socket.io客房还是Redis pub-sub?

很简单的问题。 我正在使用nodejs作为我的后端构build一个实时游戏,我想知道是否有任何信息可用,哪一个更可靠,哪个更有效? 我在我的代码中大量使用了Redis和Socket.io。 所以我想知道我应该使用Socket.io的房间还是使用redis的pub-sub更好?

更新:刚刚意识到有一个非常重要的原因,你可能想使用redis pub / sub over socket.io房间。 在发布给侦听器的情况下,使用Socket.io房间,(浏览器)客户端收到消息,使用redis实际上是收到消息的客户端(服务器端)。 因此,如果要通知所有(服务器)客户端特定于每个客户端的信息,并在传递给浏览器客户端之前做一些处理,则最好使用redis。 使用redis,你可以直接触发一个事件来生成每个用户的个人数据,就像socket.io一样,你必须一次生成所有的用户唯一的数据,然后循环遍历它们并发送他们的个人数据,房间的目的,至less对我来说。

不幸的是对于我的目的,我现在坚持使用redis。

更新2:结束开发插件只使用2个Redis连接,但仍然允许单个客户端处理,请参阅下面的答案….

如果所有客户端都可以直接访问Redis,则Redis pub / sub非常棒。 如果您有多个节点服务器,则可以将消息推送给其他服务器。

但是,如果您在浏览器中也有客户端,则需要其他的东西来将数据从服务器推送到客户端,在这种情况下,socket.io非常棒。

现在,如果在Redis存储中使用socket.io,socket.io将使用Redis pub / sub在服务器之间传播消息,服务器将消息传播到客户端。

因此,使用configuration了Redis存储的socket.io的socket.io客房对您来说可能是最简单的。

我最终编写了一个节点插件来允许多个pub-sub客户端,但是在每一个socketio连接上只需要2个redis连接,而不是一个新的连接,它应该工作在一般情况下,其他人可能会find它的用处。

这个代码假定你有socket.io运行和设置,基本上在这个例子中,任何socket.io客户端都可以连接,它总是只能使用2个redis连接,但是所有的客户端都可以订阅自己的通道。 在这个例子中,所有的客户端都会收到一条消息“甜蜜的消息! 10秒后。

socket.io示例(使用redis pub-sub):

var RPubSubFactory = require('rpss.js'); var redOne = redis.createClient(port, host), redTwo = redis.createClient(port, host); var pSCFactory = new RPubSubFactory(redOne); io.sockets.on('connection', function(socket){ var cps = pSCFactory.createClient(); cps.onMessage(function(channel, message){ socket.emit('message', message); }); io.sockets.on('disconnect', function(socket){ // Dont actually need to unsub, because end() will cleanup all subs, // but if you need to sometime during the connection lifetime, you can. cps.unsubscribe('cool_channel'); cps.end(); }); cps.subscribe('cool_channel') }); setTimeout(function(){ redTwo.publish('cool_channel', 'sweet message!'); },10000); 

实际的插件代码:

 var RPubSubFactory = function(){ var len,indx,tarr; var dbcom = false, rPubSubIdCounter = 1, clientLookup = {}, globalSubscriptions = {}; // public this.createClient = function() { return new RPubSupClient(); } // private var constructor = function(tdbcom) { dbcom = tdbcom; dbcom.on("message", incommingMessage); } var incommingMessage = function(rawchannel, strMessage) { len = globalSubscriptions[rawchannel].length; for(var i=0;i<len;i++){ //console.log(globalSubscriptions[rawchannel][i]+' incomming on channel '+rawchannel); clientLookup[globalSubscriptions[rawchannel][i]]._incommingMessage(rawchannel, strMessage); } } // class var RPubSupClient = function() { var id = -1, localSubscriptions = []; this.id = -1; this._incommingMessage = function(){}; this.subscribe = function(channel) { //console.log('client '+id+' subscribing to '+channel); if(!(channel in globalSubscriptions)){ globalSubscriptions[channel] = [id]; dbcom.subscribe(channel); } else if(globalSubscriptions[channel].indexOf(id) == -1){ globalSubscriptions[channel].push(id); } if(localSubscriptions.indexOf(channel) == -1){ localSubscriptions.push(channel); } } this.unsubscribe = function(channel) { //console.log('client '+id+' unsubscribing to '+channel); if(channel in globalSubscriptions) { indx = globalSubscriptions[channel].indexOf(id); if(indx != -1){ globalSubscriptions[channel].splice(indx, 1); if(globalSubscriptions[channel].length == 0){ delete globalSubscriptions[channel]; dbcom.unsubscribe(channel); } } } indx = localSubscriptions.indexOf(channel); if(indx != -1){ localSubscriptions.splice(indx, 1); } } this.onMessage = function(msgFn) { this._incommingMessage = msgFn; } this.end = function() { //console.log('end client id = '+id+' closing subscriptions='+localSubscriptions.join(',')); tarr = localSubscriptions.slice(0); len = tarr.length; for(var i=0;i<len;i++){ this.unsubscribe(tarr[i]); } localSubscriptions = []; delete clientLookup[id]; } var constructor = function(){ this.id = id = rPubSubIdCounter++; clientLookup[id] = this; //console.log('new client id = '+id); } constructor.apply(this, arguments); } constructor.apply(this, arguments); }; module.exports = RPubSubFactory; 

我尽力提高效率,但是在做了一些不同的速度testing之后,我认为这是我能得到的最快速度。

对于最新版本: https : //github.com/Jezternz/node-redis-pubsub