2012-01-20 40 views
6

Acabo de aprender redis y node.js Hay dos preguntas que tengo para las que no pude encontrar ninguna respuesta satisfactoria.Preguntas Redis y Node.js y Socket.io

Mi primera pregunta es sobre la reutilización de clientes redis dentro del node.js. Encontré esta pregunta y respuesta: How to reuse redis connection in socket.io?, pero no me satisfizo lo suficiente.

Ahora, si creo el cliente redis dentro del evento de conexión, se generará para cada conexión. Entonces, si tengo 20k usuarios simultáneos, habrá 20k clientes redis.

Si lo coloco fuera del evento de conexión, se generará una sola vez.

La respuesta es que crea tres clientes para cada función, fuera del evento de conexión.

Sin embargo, por lo que sé de MySQL que al escribir una aplicación que genera procesos secundarios y se ejecuta en paralelo, debe crear su cliente MySQL dentro de la función en la que está creando instancias hijo. Si lo crea fuera de él, MySQL dará un error de "servidor MySQL se ha ido" ya que los procesos secundarios intentarán usar la misma conexión. Se debe crear para cada proceso secundario por separado.

Entonces, incluso si crea tres clientes redis diferentes para cada función, si tiene 30k usuarios simultáneos que envían 2k mensajes al mismo tiempo, debería encontrarse con el mismo problema, ¿no? Entonces, cada "usuario" debería tener su propio cliente redis dentro del evento de conexión. ¿Estoy en lo cierto? Si no, ¿cómo node.js o redis manejan las solicitudes concurrentes, de manera diferente a MySQL? Si tiene su propio mecanismo y crea algo así como procesos secundarios dentro del cliente redis, ¿por qué entonces necesitamos crear tres clientes redis diferentes? Uno debería ser suficiente.

Espero que la pregunta sea clara.

- ACTUALIZACIÓN -

he encontrado una respuesta a la siguiente pregunta. http://howtonode.org/control-flow No hay necesidad de responder, pero mi primera pregunta sigue siendo válida.

- ACTUALIZACIÓN -

Mi segunda pregunta es la siguiente. Tampoco soy tan bueno en JS y Node.js. Entonces, por lo que sé, si necesita esperar un evento, necesita encapsular la segunda función dentro de la primera función. (Aún no conozco la terminología). Déjame dar un ejemplo;

socket.on('startGame', function() { 
    getUser(); 
    socket.get('game', function (gameErr, gameId) { 
     socket.get('channel', function (channelErr, channel) { 
      console.log(user); 
      client.get('games:' + channel + '::' + gameId + ':owner', function (err, owner) { //games:channel.32:game.14 
       if(owner === user.uid) { 
    //do something 
       } 
      }); 
     } 
    }); 
}); 

lo tanto, si estoy aprendiendo correctamente, se necesita para ejecutar todas las funciones dentro de la función, si tengo que esperar la respuesta de E/S. De lo contrario, el mecanismo no bloqueante de node.js permitirá que se ejecute la primera función, en este caso obtendrá el resultado en paralelo, pero la segunda función podría no tener el resultado si lleva tiempo obtenerla. Entonces, si obtiene un resultado de redis, por ejemplo, y usará el resultado dentro de la segunda función, debe encapsularlo dentro de la función redis get. De lo contrario, se ejecutará la segunda función sin obtener el resultado.

Entonces, en este caso, si necesito ejecutar 7 funciones diferentes y la función 8. necesitará el resultado de todas ellas, ¿tengo que escribirlas así, recursivamente? O me estoy perdiendo algo.

Espero que esto también esté claro.

Muchas gracias,

+1

Por cierto, para completar su propia respuesta a su segunda pregunta, también puede consultar las bibliotecas de control de flujo "async" y "step". –

Respuesta

2

Así, cada "usuario" debe tener su propio cliente Redis dentro del evento de conexión. ¿Estoy en lo cierto?

En realidad, no está :)

El caso es que Node.js es muy a diferencia de, por ejemplo, PHP. node.js no genera procesos secundarios en conexiones nuevas, que es una de las razones principales por las que puede manejar fácilmente grandes cantidades de conexiones simultáneas, incluidas conexiones de larga duración (Comet, Websockets, etc.). node.js procesa eventos secuencialmente utilizando una cola de eventos en un solo proceso. Si desea utilizar varios procesos para aprovechar los servidores multi-core o múltiples servidores, tendrá que hacerlo manualmente (sin embargo, cómo hacerlo está más allá del alcance de esta pregunta).

Por lo tanto, es una estrategia perfectamente válida para usar una sola conexión Redis (o MySQL) para servir a una gran cantidad de clientes. Esto evita la sobrecarga de instanciar y terminar una conexión de base de datos para cada solicitud de cliente.

0

Por lo tanto, cada "usuario" debe tener su propio cliente redis dentro del evento de conexión . ¿Estoy en lo cierto?

No debe crear un nuevo cliente Redis para cada usuario conectado, esa no es la forma correcta de hacerlo. En su lugar, solo cree 2-3 clientes como máximo y úselos.

Para obtener más información de pago a esta pregunta:

How to reuse redis connection in socket.io?

0

En cuanto a la primera pregunta: La "respuesta correcta" puede hacer que usted piensa que son buenos con una sola conexión. En realidad, cada vez que está haciendo algo que está esperando en un IO, un temporizador, etc., en realidad está haciendo que el nodo ejecute el método de espera en la cola. Por lo tanto, si usa solo 1 conexión única, limitará el rendimiento del hilo que está trabajando (una sola CPU) a la velocidad de redis, que es probablemente unos pocos cientos de devoluciones de llamada por segundo (las devoluciones de llamada en espera que no sean redis aún continúe): aunque este no es un rendimiento pobre, no hay razón para crear este tipo de limitación. Se recomienda crear algunas (5-10) conexiones para evitar este problema en su totalidad. Este número aumenta para las bases de datos más lentas, p. MySQL, pero depende del tipo de consultas y de los detalles del código.

Tenga en cuenta que debe ejecutar unos pocos trabajadores en su servidor, según el número de CPU que tenga, para obtener el mejor rendimiento. Con respecto a la 2da Pregunta: Es una práctica mucho mejor, nombrar las funciones, una después de la otra, y usar los nombres en el código en lugar de definirlo sobre la marcha. En algunas situaciones, reducirá el consumo de memoria.