10 noviembre, 2009

NodeJS



“Evented I/O for V8 JavaScript”— es un entorno JavaScript construido sobre el rapidísimo motor V8 que provee funcionalidad de entrada y salida basada en eventos para construir servidores TCP y HTTP altamente concurrentes. El diseño de la API es soberbio — todo se consigue usando eventos y llamadas callback de JavaScript (incluso el acceso típico a archivos) y la pequeña librería estándar ya contiene soporte completo de HTTP y DNS.

En general es muy similar a Twisted (Python) y otras por el estilo, pero la sintaxis de funciones anónimas de JavaScript parece más natural que su equivalente en Python.

El protocolario "Hola mundo":

var sys = require('sys'), 
   http = require('http');
http.createServer(function (req, res) {
  setTimeout(function () {
    res.sendHeader(200, {'Content-Type': 'text/plain'});
    res.sendBody('Hello World');
    res.finish();
  }, 2000);
}).listen(8000);
sys.puts('Server running at http://127.0.0.1:8000/');

O un servidor que escucha en el puerto 7000 y devuelve lo mismo que recibe (echo):

var tcp = require('tcp');
var server = tcp.createServer(function (socket) {
  socket.setEncoding("utf8");
  socket.addListener("connect", function () {
    socket.send("hello\r\n");
  });
  socket.addListener("receive", function (data) {
    socket.send(data);
  });
  socket.addListener("eof", function () {
    socket.send("goodbye\r\n");
    socket.close();
  });
});
server.listen(7000, "localhost");

El objetivo de Node es proporcionar una manera fácil de crear programas escalables para redes. En el ejemplo anterior, los dos segundos de retraso no impiden que el servidor gestione solicitudes nuevas. Node indica al sistema operativo (a través de epoll, kqueue, /dev/poll, o select) que debe ser notificado cuando los 2 segundos de arriba pasen o si se hace una nueva conexión, y entonces entra en suspenso. Si alguien nuevo se conecta, entonces se ejecuta la función callback, si el tiempo de espera se termina, se ejecuta la llamada callback interna. Cada conexión consume sólo una pequeña parte del heap.

Esto contrasta con el modelo de concurrencia más común hoy en día en el que se usan hilos del sistema operativo. La gestión de redes basada en hilos es relativamente ineficiente y muy difícil de usar. Node mostrará una mejor eficiencia del uso de la memoria bajo altas cargas que los sistemas que asignan pilas de hilos de 2mb para cada conexión. Además, los usuarios de node no deben preocuparse de bloquear el proceso - no hay locks. Casi ninguna función en node usa directamente la entrada/salida, por lo que el proceso nunca se bloquea. Debido a que nada bloquea, los programadores menos expertos pueden desarrollar sistemas rápidos.

Node es similar en diseño a sistemas como la Event Machine de Ruby o Twisted de Python, y está influido por ellos. Node lleva el modelo de eventos un poco más lejos - presenta el bucle de eventos como una construcción del lenguaje en lugar de como una biblioteca. En otros sistemas, siempre hay una llamada bloqueante para iniciar el bucle de eventos. Normalmente se define el comportamiento a través de llamadas callback al comienzo de un script, y al final se inicia un servidor a través de una llamada bloqueante como EventMachine::run(). En node no existe esa llamada bucle-de-inicio-del-evento. node simplemente entra en el bucle de eventos después de ejecutar el script de entrada. node sale del bucle de eventos cuando no hay más llamadas callback a realizar. Este comportamiento es como el del Javascript del navegador — el bucle de eventos está oculto para el usuario.

HTTP es un protocolo de primera clase en node. La Biblioteca HTTP de node ha crecido a partir de las experiencias del autor desarrollando y trabajando con servidores web. Por ejemplo, enviar datos por streaming a través de la mayoría de frameworks web es imposible. node intenta corregir estos problemas con su parser HTTP y su API. La infraestructura puramente basada en eventos de node constituye una buena base para crear bibliotecas web o frameworks.

Pero ¿qué pasa con la concurrencia de múltiples procesadores? Los procesos son necesarios para escalar a ordenadores multi-núcleo, sin hilos con memoria compartida. Los fundamentos de los sistemas escalables son conexiones de red rápidas y diseño no bloqueante - el resto es intercambio de mensajes. En futuras versiones, node podrá generar nuevos procesos (usando la API de Web Workers), pero eso es algo que ya encaja muy bien en el diseño actual.

Via Simon Willison.

Publicar un comentario en la entrada

Últimos links en indiza.com