sub socketio socket pub node multiple clients node.js redis socket.io publish-subscribe

node.js - socketio - socket io sticky session



¿Qué debería estar usando? Socket.io habitaciones o redis pub-sub? (2)

Pregunta bastante simple. Estoy creando un juego en tiempo real usando nodejs como mi backend y me pregunto si hay información disponible sobre cuál es más confiable y cuál es más eficiente. Estoy usando mucho Redis y Socket.io en todo mi código. Entonces, ¿quiero saber si debería utilizar Socket.io''s Rooms o si sería mejor usar redis '' pub-sub ?

Actualización: Me acabo de dar cuenta de que hay una razón muy importante por la que puede querer usar redis pub / sub over socket.io rooms. Con las salas Socket.io cuando publica para los oyentes, los clientes (del navegador) reciben el mensaje, con redis en realidad son los clientes (redis ~ en el servidor) los que reciben los mensajes. Por este motivo, si desea informar a todos los clientes (del servidor) sobre la información específica de cada cliente y tal vez realizar un procesamiento antes de pasar a los clientes del navegador, es mejor utilizar redis. Usando redis, puede simplemente disparar un evento para generar datos individuales de cada usuario, donde, al igual que con socket.io, debe generar todos los datos únicos de los usuarios a la vez, luego hacer un bucle a través de ellos y enviarles sus datos individuales, lo que casi derrota al Propósito de las habitaciones, al menos para mí.

Desafortunadamente para mis propósitos estoy atascado con redis por ahora.

Actualización 2: Terminé desarrollando un complemento para usar solo 2 conexiones redis pero aún así permitir el procesamiento individual del cliente, vea la respuesta a continuación ...


Redis pub / sub es excelente en caso de que todos los clientes tengan acceso directo a redis. Si tiene varios servidores de nodo, uno puede enviar un mensaje a los demás.

Pero si también tiene clientes en el navegador, necesita algo más para enviar datos de un servidor a un cliente, y en este caso, socket.io es excelente.

Ahora, si usa socket.io con la tienda Redis, socket.io usará el pub / sub Redis debajo del capó para propagar mensajes entre servidores, y los servidores propagarán mensajes a los clientes.

Por lo tanto, usar las salas socket.io con socket.io configurado con la tienda Redis es probablemente el más simple para usted.


Terminé escribiendo un plugin de nodo para permitir muchos clientes de pub-sub, pero solo requiero 2 conexiones redis en lugar de una nueva en cada conexión de socketio, debería funcionar en general, pensé que otra persona podría encontrarle un uso.

Este código asumió que tiene socket.io ejecutándose y configurando, básicamente en este ejemplo cualquier número de clientes socket.io puede conectarse y siempre seguirá utilizando solo 2 conexiones redis, pero todos los clientes pueden suscribirse a sus propios canales. En este ejemplo, todos los clientes reciben un mensaje ''¡dulce mensaje!'' después de 10 segundos.

Ejemplo con socket.io (utilizando 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);

Código actual del plugin:

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;

Mucked alrededor y traté de mejorar la eficiencia tanto como pude, pero después de hacer diferentes pruebas de velocidad, llegué a la conclusión de que era lo más rápido que podía conseguirlo.

Para la versión actualizada: https://github.com/Jezternz/node-redis-pubsub