2012-04-13 18 views
14

Soy nuevo en redis pub/sub. Tengo un servicio de chat en el sistema que es como IM. Entonces me gustaría usar redis pub/sub. Al examinar las muestras, la mayoría de ellas están diseñadas en base a una sala de chat. En mi sistema tendré múltiples salas de chat entre usuarios como;¿Cómo diseñar redis pub/sub para un sistema de mensajería instantánea?

A:B 
A:C 
D:C 
E:F 

Por lo tanto, las líneas de arriba son las habitaciones. Y he implementado el servidor con node.js como a continuación;

var store = redis.createClient(); 
var pub = redis.createClient(); 
io.sockets.on('connection', function (socket) { 
    var sub = redis.createClient(); 

    sub.on("message", function(pattern, data){ 
      data = JSON.parse(data); 
     socket.send(JSON.stringify({ type: "chat", key: pattern, nick: data.nickname, message: data.text })) 
     } 
    }); 

    socket.on('message', function (messageData) { 
     store.incr("messageNextId", function(e, messageId) { 
     var room = "" 
     var from = messageData.clientId > socket.nickname ? socket.nickname : messageData.clientId; 
     var to = messageData.clientId < socket.nickname ? socket.nickname : messageData.clientId; 
      room = from + ":" + to; 

     var message = { id: messageId, nickname: socket.nickname, text: messageData.text }; 
     store.rpush("rooms:" + room, JSON.stringify(message), function(e, r) { 
      pub.publish(room, JSON.stringify(message)) 
     }); 
    }); 
}); 

Como puede ver, estoy creando un nuevo suscriptor Redis para cada conexión. En otras muestras de la sala de chat, el cliente de suscripción redis se crea globalmente. Y solo existen tres conexiones todo el tiempo y eso resuelve su problema porque cuando un editor publica un mensaje, todos los clientes conectados deben obtenerlo. Pero tengo una restricción aquí. Quiero abrir una sesión de chat entre dos usuarios y solo estos usuarios deben ser suscriptores. El código anterior funciona como me gustaría, pero no sé si está bien para redis crear un nuevo cliente de suscripción para cada conexión.

Sería genial escuchar sus sugerencias. Gracias por adelantado.

Respuesta

20

Como siempre, necesita comparar este tipo de cosas para su propio caso de uso: no es posible dar consejos generales. Es posible que necesite aumentar la cantidad máxima de archivos abiertos en su sistema, ya sea para todo el sistema o para el usuario redis. Esto también se aplica al usuario que ejecuta su servidor web, por supuesto.

Dicho esto, debe asegurarse de escuchar socket.on('disconnect') y quit() el suscriptor redis cuando un usuario se va. También podría estar interesado en saber que socket.io tiene un backend redis, que aprovecha redis pub/sub, y también tiene el concepto de salas, por lo que puede ahorrarse algunos problemas al usar eso ya que ya depende de socket .io.

Editar: Después de una comprobación rápida, me sale este mensaje de error Redis después de 991 suscriptores:

Ready check failed: Error: Error: ERR max number of clients reached 

Este es el valor predeterminado redis.conf:

# Set the max number of connected clients at the same time. By default 
# this limit is set to 10000 clients, however if the Redis server is not 
# able ot configure the process file limit to allow for the specified limit 
# the max number of allowed clients is set to the current file limit 
# minus 32 (as Redis reserves a few file descriptors for internal uses). 
# 
# Once the limit is reached Redis will close all the new connections sending 
# an error 'max number of clients reached'. 
# 
# maxclients 10000 

Mi sistema (Ubuntu 11.11) viene con un límite predeterminado de nofile de 1024, por lo que mi prueba rápida debería fallar después de 992 clientes conectados, lo que parece ser justo desde la prueba (también tengo un cliente para el editor). Mi sugerencia para usted es de inspeccionar su límite nofile (en mi sistema está en /etc/security/limits.{conf,d/*} y sus Redis ajuste maxclients, y luego de referencia, punto de referencia, referencia!

+0

Gracias por la respuesta detallada. Yo sabía que socket.io tiene el concepto de sala pero no me di cuenta de que está usando pub/sub entre bastidores. Voy a probar eso. Y seguro, comenzaré las pruebas de referencia, actualmente estoy tratando de encontrar un buen punto de partida. Gracias por el sugerencias. –

+0

@ AliErsöz: genial. Si descubres que mi respuesta fue satisfactoria, considera aceptarla como la respuesta correcta haciendo clic en la marca de verificación grande en la esquina superior izquierda. –

Cuestiones relacionadas