Node.js - Eventos para Todos

4,694 views

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,694
On SlideShare
0
From Embeds
0
Number of Embeds
411
Actions
Shares
0
Downloads
64
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • ** QUE HACE: Esperando. Entra conexión, consultás la DB, y esperas resultados. Escribís un archivo, y esperás q se escriba. Encodeás un video, y esperás q termine. ** CACHING: Memcached ** WORKERS: Gearman, o ActiveMQ / RabbitMQ ** FASTER DB: NoSQL (MongoDB, CouchDB)
  • No podés simplemente abrir nuevos procesos o threads para cada conexión NGINX basado en eventos, uso de memoria muy bajo APACHE lanza un thread por request (o proceso dependiendo de la conf) THREADS están mucho tiempo bloqueados por operaciones I/O EVENTOS son mejores cuando se emplea mucho tiempo esperando recursos
  • ** V8: Sin soporte DOM
  • ** PROPS: Propiedades de objetos se cambian en runtime en JS: diccionarios de propiedades Variables de instancia tienen offsets fijos por compilador. V8 crea clases ocultas, una para cada propiedad agregada y las transiciones de clases representan cambios en las propiedades del obj (solo 1ra vez) ** CODIGO MAQUINA: en primera ejecucion de JS, se compila a maquina, NO a codigo intermedio ** GARBAGE: cuando se corre GC, se bloquea. Cada ciclo GC procesa parte del heap. En V8 3.7 (node 0.6) hay un nuevo GC q permite heaps de tamaño ilimitado
  • ** Tornado (Python). Tambien Event Machine (Ruby)
  • ** LIBEIO: similar a LIBEV, por Marc Lehmann. Puede ser usado con cualq lib de eventos, o en modo POLLING. Se basa unicamente en POSIX threads. Usa threads internamente, es usado por Node.JS para acceso de file/network, integrato en node via LIBEV ** LIBEV: tamb por Marc Lehmann. Notificacion asincrona de cambios en file descriptor a traves de ev_io() ** LIBUV: Separa lo propio del OS de V8 ** ReadFile(): mucho codigo JS, arriba de fs.open(), q es un wrapper sobre C++ Open(), q usa libeio
  • Node sobre Windows es tan rapido como Linux Soporte desde Windows Server 2003 a Windows 7
  • ** BUFFER: Fuera del heap V8. Conversion a JS a través de encoding (binary, utf8, ascii, etc.) ** C-ARES: gethostbyname(), consultas DNS ** CHILD_PROCESSES: fork() esta en tierra JS, uso particular de spawn(), con mensajeo IPC ** CRYPTO: crear hashes, ciphers con diferentes algoritmos, firmar con private keys, verificar firmas ** HTTP_PARSER: NO allocation, NO buffer ** TIMER: setTimeout() una sola vez, setInterval() repetidas
  • * Todo pasa en un solo thread * Cola de eventos vacia * Al abrir archivo, se agrega tarea al event loop * Cuando hay tiempo libre, se procesa el event loop * El I/O se realiza usando herramientas del kernel que NO bloquean: epoll(), select(), kqueue() * El event loop sigue esperando * Kernel notifica al event loop q la tarea ta realizada * Event loop ejecuta callback * Cuando el event loop está vacío, el programa termina
  • ** SOLO THREAD: todo lo que bloquea el thread ppal imposibilita procesar nuevas requests ** Para VOS: si tu código usa I/O de node, ese I/O NO bloquea ** Llamadas I/O es el punto en el que Node.js procesa otras requests. Entonces Node.js espera que las requests se procesen rápido. Tareas intensivas de CPU debieran ser en otro proceso
  • Como Node.JS corre en un solo proceso, esta atado a un solo CPU ** Usando al SO: el kernel hace load balancing de las conexiones a traves de los CPUs ** CLUSTER: usa muchos workers (en diferentes CPUs). Alternativa para Node < 0.6
  • ** RUBY: Usá CoffeeScript
  • ** Los paquetes pueden instalarse local o globalmente
  • ** COMMONJS: defines JS APIs for any purpose, such as server side JS. Amongst the things it defines, are modules ** The EXPORTS object is created by the module system. If you want your module to be a class, assign the export object to MODULE.EXPORTS
  • ** ROUTING: Including support for HTTP methods ** MIDDLEWARE: for manipulating all requests, or for specific routes ** VIEW RENDERING: with different template engines, and including partials (sort of like CakePHP elements) ** SESSION SUPPORT: part of Connect, can be configured even with Redis ** ENVIRONMENTS: Can specify different middleware for each environment, and change settings
  • ** MIDDLEWARES: order is important. ** BodyParser() allows the parsing of forms (including JSON posted data as part of body) ** Other middlewares include: cookieParser(), session()
  • ** JADE is one of the view engines available: $ npm install jade
  • With route middleware, it's easy to add authentication
  • * GENERIC_POOL: definis name, max (conexiones), create(), y destroy(). Luego adquiris con acquire(), y liberas con release() * ASYNC: SERIES (): corre en orden y stop on error, llama callback() cuando terminado. PARALLEL() no para si hay error. WATERFALL() es como series(), p cada resultado se pasa com arg al siguiente * NODEUNIT: usa modulo assert de node * SOCKET.IO: transportes WebSocket, Flash, AJAX long polling, AJAX multipart streaming, JSONP polling. IE 5.5+, Safari 3+, Chrome 4+, Firefox 3+, Opera 10.61+. Mobile (iPhone, iPad, Android, WebOs) * UNDERSCORE: Array, funciones, Object
  • Node.js - Eventos para Todos

    1. 1. Node.js ¡Eventos para todos! BarCamp BA 2011 Mariano Iglesias @mgiglesias (No es un plan del gobierno)
    2. 2. ¿Quién habla? <ul><li>Miramarense por elección
    3. 3. No sirvo para otra cosa más que programar
    4. 4. CakePHP & Lithium
    5. 5. Muu..uuchos proyectos FOSS </li><ul><li>C++, Python, PHP, Node.js </li></ul><li>Amo Apple </li></ul>
    6. 6. Tirá todo lo que hiciste <ul>Si creés que eso es positivo, debés creer que Grondona es un tipo honesto </ul><ul>Usá diferentes tecnologías para resolver problemas distintos </ul><ul><li>PHP
    7. 7. Python
    8. 8. Node.js
    9. 9. C++
    10. 10. NGINx / Lighttpd </li></ul>
    11. 11. ¿En qué estaba pensando Ryan? <ul><li>¿Qué hace normalmente una aplicación?
    12. 12. ¿Qué puedo hacer? </li><ul><li>Agregar cache
    13. 13. Agregar workers
    14. 14. Mejor manejo de DB
    15. 15. Escalado Vertical : más hardware
    16. 16. Escalado Horizontal : más servers </li></ul><li>¿No llegás a los 10k usuarios concurrentes? </li></ul>
    17. 17. Threads vs. eventos <ul>http://blog.wefaction.com/a-little-holiday-present </ul><ul>Me niego a decir hilos </ul>
    18. 18. ¿Qué es Node.js? <ul>Simplificando, es JavaScript en el servidor </ul><ul>Engine V8 JavaScript </ul><ul>I/O basada en Eventos </ul><ul>+ </ul><ul>= </ul>
    19. 19. Engine V8 <ul><li>Acceso a propiedades (clases ocultas)
    20. 20. Código máquina
    21. 21. Garbage collection </li></ul><ul>La rapidez como mantra </ul><ul>http://code.google.com/apis/v8/design.html </ul>
    22. 22. La rapidez no es lo único <ul>“ Tiene que haber un balance entre performance y productividad .“ “ Si no fuese así, seguiríamos programando en Assembler “ </ul><ul>Dedicado a los benchmarks de Erlang, Tornado, etc. </ul>
    23. 23. I/O basada en Eventos <ul><li>libeio : async I/O
    24. 24. libev : event loop </li></ul><ul><ul><li>libuv </li></ul></ul>db. query (). select ( '*' ). from ( 'users' ). execute ( function () { fs. readFile ( 'settings.json' , function () { // ... }); });
    25. 25. Libuv == Node.exe http_simple (/bytes/1024) over 1-gbit network, with 700 concurrent connections: windows-0.5.4 : 3869 r/s windows-latest : 4990 r/s linux-latest-legacy : 5215 r/s linux-latest-uv : 4970 r/s
    26. 26. Más cosas <ul><li>buffer : muchos bytes
    27. 27. c-ares : DNS asíncrono
    28. 28. child_process : spawn(), exec(), fork() (0.5.x)
    29. 29. crypto : OpenSSL
    30. 30. http_parser : parser HTTP más rápido que Berlusconi
    31. 31. timer : setTimeout(), setInterval() </li></ul>
    32. 32. Primer servidor node.js var http = require ( 'http' ); http. createServer ( function (req, res) { res. writeHead ( 200 , { 'Content-type' : 'text/plain' }); res. end ( 'Hello World!' ); }). listen ( 1337 ); console. log ( 'Server running at http://localhost:1337' );
    33. 33. Regla #1: NO BLOQUEAR
    34. 34. Regla #1: NO BLOQUEAR <ul><li>¿Querés abrir un archivo? Tirá el open, y esperá </li><ul><li>Pero mientras esperás, ¡laburá canejo! </li></ul><li>¿Llamás a un binario para encodear? Nuevamente, esperá </li><ul><li>Pero acordate, seguí laburando </li></ul><li>Todo esto es posible gracias a la programación basada en... EVENTOS (obvio) </li></ul>
    35. 35. Regla #2: TERMINA RAPIDO
    36. 36. Regla #2: TERMINA RAPIDO <ul><li>Si tenés que procesar algo grande, pensá en subprocesos
    37. 37. Si no tenés subprocesos, bancatela y programá en C++ </li><ul><li>Después me lo agradecés </li></ul><li>Lo importante es que si lo vas a hacer, hacelo rápido </li></ul>
    38. 38. Entendiendo el event loop eventos Abrir archivo Sigo trabajando... FIN En espera Procesar loop Kernel I/O KERNEL Listo Callback
    39. 39. Entendiendo el event loop <ul><li>Hay un solo thread corriendo en Node.js
    40. 40. No hay ejecución paralela... para VOS </li></ul>var http = require ( 'http' ); http. createServer ( function (req, res) { console. log ( 'New request' ); // Block for five seconds var now = new Date (). getTime (); while ( new Date (). getTime () < now + 5000 ) ; // Response res. writeHead ( 200 , { 'Content-type' : 'text/plain' }); res. end ( 'Hello world!' ); }). listen ( 1337 ); console. log ( 'Server running at http://localhost:1337' );
    41. 41. ¡¿ UN THREAD ?! ¿Y qué hago con este monstruo de 48 núcleos?
    42. 42. ¡Tengo más de 1 procesador! <ul>:1337 </ul><ul>:1338 </ul><ul>:1339 </ul><ul>Usando load balancer </ul><ul>Usando al SO </ul>var http = require ( 'http' ), cluster = ...; var server = http. createServer ( function (req, res) { res. writeHead ( 200 , { 'Content-type' : 'text/plain' }); res. end ( 'Hello world!' ); }); cluster (server). listen ( 1337 ); <ul>http://learnboost.github.com/cluster </ul>
    43. 43. ¡Tengo más de 1 procesador! var http = require ( 'http' ), cluster = require ( 'cluster' ); if (cluster.isMaster) { cluster. startMaster ({ workers: 4 }); process. on ( 'SIGCHLD' , function () { cluster. spawnWorker (); }); } else { http. createServer ( function (req, res) { res. writeHead ( 200 , { 'Content-type' : 'text/plain' }); res. end ( 'Hello world!' ); }). listen ( 1337 ); }
    44. 44. Me convenciste <ul><li>Node.js suena interesante... ¡pero es Javascript!
    45. 45. Ok, Javascript no es tan malo... Pero en PHP tengo un montón de documentación
    46. 46. Bueno, acepto la comunidad ... Pero no tengo todas las librerías que tengo en Java
    47. 47. Yo soy cool, y uso Ruby nomás </li></ul><ul>www.nodojs.org </ul>
    48. 48. Módulos, módulos, módulos $ curl http://npmjs.org/install.sh | sh $ npm install db-mysql <ul>Hay más de 4700 paquetes, y más de 14 se agregan cada día </ul>
    49. 49. Módulos, módulos, módulos var m = require ( './module' ); m. sum ( 1 , 3 , function (err, res) { if (err) { return console. log ( 'ERROR: ' + err); } console. log ( 'RESULT IS: ' + res); }); exports.sum = function (a, b, callback) { if ( isNaN (a) || isNaN (b)) { return callback ( new Error ( 'Invalid parameter' )); } callback ( null , a+b); };
    50. 50. Mostrame un lenguaje, y te vomito frameworks <ul><li>Entornos configurables
    51. 51. Middleware
    52. 52. Routing
    53. 53. Vistas (duh!)
    54. 54. Sesiones (duh por dos!) </li></ul><ul>http://expressjs.com </ul>
    55. 55. express var express = require ( 'express' ); var app = express. createServer (); app. get ( '/' , function (req, res) { res. send ( 'Hello world!' ); }); app. listen ( 3000 ); console. log ( 'Server listening in http://localhost:3000' ); app. configure ( function () { app. use (express. bodyParser ()); }); app. configure ( 'dev' , function () { app. use (express. logger ()); }); $ NODE_ENV=dev node app.js
    56. 56. express app. configure ( function () { app. set ( 'views' , __dirname + '/views' ); app. set ( 'view engine' , 'jade' ); }); app. get ( '/users/:id?' , function (req, res, next) { if (!req.params.id) { return next (); } if (!users[req.params.id]) { return next ( new Error ( 'Invalid user' )); } res. send (users[req.params.id]); }); app. get ( '/users' , function (req, res) { res. render ( 'index' , { layout: false , locals: { users: users } }); }); html body h1 Node.js ROCKS ul - each user, id in users li a(href='/users/#{id}') #{user.name} <ul>views/index.jade </ul>
    57. 57. Middleware en rutas function getUser (req, res, next) { if (!req.params.id) { return next (); } else if (!users[req.params.id]) { return next ( new Error ( 'Invalid user' )); } req.user = users[req.params.id]; next (); } app. get ( '/users/:id?' , getUser, function (req, res, next) { if (!req.user) { return next (); } res. send (req.user); });
    58. 58. node-db <ul><li>¿Para qué?
    59. 59. Bases de datos soportadas
    60. 60. Consultas </li><ul><li>Manuales
    61. 61. API </li></ul><li>Tipos JSON </li><ul><li>Buffer </li></ul></ul><ul>http://nodejsdb.org </ul>
    62. 62. node-db var mysql = require ( 'db-mysql' ); new mysql. Database ({ hostname: 'localhost' , user: 'root' , password: 'password' , database: 'db' }). connect ( function (err) { if (err) { return console. log ( 'CONNECT error: ' , err); } this . query (). select ([ 'id' , 'email' ]). from ( 'users' ). where ( 'approved = ? AND role IN ?' , [ true , [ 'user' , 'admin' ] ]). execute ( function (err, rows, cols) { if (err) { return console. log ( 'QUERY error: ' , err); } console. log (rows, cols); }); });
    63. 63. Para ir pispeando <ul><li>Pool de conexiones con generic_pool
    64. 64. Tareas paralelas con async
    65. 65. Unit Testing con nodeunit
    66. 66. Socket.io
    67. 67. Libs para MongoDB, Redis, CouchDB...
    68. 68. _ (underscore.js) </li></ul>
    69. 69. ¿Preguntas? <ul>@mgiglesias http://marianoiglesias.com.ar </ul>

    ×