Introducción a






En Producción

Quién soy



Ingeniero de software con 15+ años de experiencia
Desarrollador senior en MediaSmart Mobile
Cacharreador impenitente desde siempre
@pinchito, alexfernandez, alejandrofer

Guión (ajustable)


Introducción rápida a node.js


Continuaciones


Node Package Manager


Despliegue


Escalabilidad

Node.js



Introducción rápida

Breve historia de Node.js


Creado por Ryan Dahl (2009)


Usa el motor de Chrome JS: V8 (en cómic)
Software libre (código fuente)

Soporte de Joyent y StrongLoop

Tres generaciones


Procesos: CGI, PHP core


Hilos: Apache MTM, Java Servlets


Eventos: nginx, node.js


Modelo de ejecución

Asíncrono

No bloqueante

Dirigido por eventos


Servidores similares:

Python: Tornado, Twisted

Ruby: EventMachine

Java: Akka


Fuente: nodejs.org/about, Wikipedia

¿Eventos? ¿Por qué no hilos?


Un programador tenía un problema.

Pensó para sí mismo,

"Ya sé, ¡lo resolveré con hilos!".

tiene Ahora problemas. dos él

Adaptado de: Davidlohr Bueso

Node.js es rápido

¿Pero cómo de rápido?


No para correr código secuencial

... pero sí en ejecución concurrente


Sólo un hilo en ejecución (sin hilos)

Multi-proceso usando el módulo cluster


Node.js es muy escalable

Node.js es muy lineal

Fuente: MediaSmart Mobile

Historia de éxito: MediaSmart Mobile


Plataforma inicial: un ingeniero durante un año

Plataforma actual: tres ingenieros durante otro año

Sirve anuncios en móvil para campañas performance


Aguanta 10K peticiones/segundo (al menos)

Escala a 25 servidores (que sepamos)

Latencia < 80 ms


Fuente: MediaSmart Mobile

Historia de Éxito: PayPal

Página de Resumen de Cuentas


2 ingenieros durante 4 meses

Desarrollado dos veces más rápido que la versión Java

33% menos código, 40% menos ficheros


Aguanta dos veces más peticiones por segundo

Tiempos de respuesta un 35% más rápidos


Fuente: Node.js at PayPal

Historia de Éxito: LinkedIn


Backend de apps móviles (2011)


Migración desde Ruby on Rails

De 15 instancias a 4 con node.js

El doble de carga que Ruby on Rails


Actualmente migrando toda su infraestructura


Fuente: VentureBeat

Demo time!

'use strict';
var net = require('net');
var server = net.createServer(function(connection) {
    console.log('Connection open');
    connection.write('Hello?\n');
    connection.on('data', function(data) {
        if (String(data).trim() != 'hello') {
            connection.write('ERROR\n');
        } else {
            connection.end('world\n');
            console.log('Connection closed');
        }
    });
});
var port = 8080;
server.listen(port);
console.log('Server listening on port %s', port);

Servidor de sockets sencillo

Continuaciones

Introducción al infierno de las callbacks

Continuaciones


Concepto de programación funcional


CPS: Continuation-passing Style


El estado pasa como parámetros y clausuras


Ideal para llamadas asíncronas

Infierno de las Callbacks


La temida pirámide de callbacks


Infinitas continuaciones anidadas


Abuso de lambdas (funciones anónimas)


Difícil de seguir, depurar y refactorizar


¿Son los GOTOs modernos?

Soluciones Sencillas


Usar funciones con nombre


Crear un objeto con funciones con nombre

Las clausuras se convierten en atributos


Usar async: async.waterfall()


Usar eventos: EventEmitter

Otros modelos


Promesas


Programación reactiva


Generadores: casi listos


Corutinas: falta bastante todavía


Demo time again!


Revisar la pirámide de callbacks


Código original: simplecached client


Explorar varios métodos diferentes


No dejar más de dos callbacks anidadas

NPM


Node Package Manager

Anatomía de un paquete (o módulo)


Fichero Readme: README.md

Definición: package.json

Punto de entrada: index.js

Código: lib/

Documentación: doc/

Binarios: bin/

Comandos NPM


  • npm install: instala uno o más paquetes
  • npm install -g: instalación global
  • npm update: actualiza uno o más paquetes
  • npm remove: elimina un paquete
  • npm test: corre las pruebas


Fuente: npm-index

Resolución de directorios

Local:

            node_modules
../node_modules
../../node_modules
...
$HOME/node_modules
./node_modules

Global:

{prefix}/lib/node_modules

donde {prefix} suele ser /usr/local


Fuente: npm-folders

aNATOMía de un package.json

{
"name": "simplecached",
"version": "0.0.1",
"description": "Simplified memcached server.",
"contributors": ["Alex Fernández <alexfernandeznpm@gmail.com>"],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/alexfernandez/simplecached"
},
"dependencies": {
"testing": "1.2.x"
},
"keywords" : ["simplecached", "didactic", "memcached", "caching"],
"bin": {
"simplecached": "bin/server.js"
},
"scripts": {
"test": "node test.js"
},
}

Fuente: package.json

Demo time!

Paquete educactivo simplecached


Instalación:

npm install simplecached

Revisar package.json


Correr las pruebas

npm test

Despliegue

Automatización


Tres reglas básicas:


  • Un botón único

  • Sin intervención humana

  • Fallos claros y llamativos

Gestión de código


Sistema distribuido: git


git en hosting: GitHub


Integrador ejecutivo


Pull Requests

Calidad del código


Revisar cada Pull Request:

  • 4 eyes
  • +1 x 3


Revisar el código antes de desplegar

¡automáticamente!

Usar JSLint (versión talibán)

JSHint (muy configurable)

Pruebas


Pruebas asíncronas


Suite de pruebas unitarias


Suite de pruebas de integración


Automatización de pruebas


Integración continua


Integrar cada cambio


Desplegar en entorno de pruebas


Realizar pruebas exhaustivas

¡automáticas!


Travis-CI

(Ejemplo)

Pruebas de carga


Paquete loadtest

Apache ab


Detección de regresiones:

Realizar pruebas de carga en cada integración


¡Pruebas automáticas!

API de control

Despliegue Continuo


Desplegar cada cambio


Entre 5 y cientos de despliegues al día


No permite que se acumulen los cambios


Aumento (paradójico) de la estabilidad

Anatomía de un despliegue exitoso


Estructura


Escalabilidad


Fuente: Danny MacAskill's Imaginate

Escalabilidad en una máquina


Usar el módulo cluster


Master + n workers

Comparten conexiones


Reiniciar worker cada pocos minutos:

  • protege de memory leaks
  • despliegues más sencillos

Escalabilidad entre máquinas


Servidores sin estado


Operaciones idempotentes


Múltiples frontales balanceados


Base de datos compartida

Todos contra la Base de datos


Arquitectura escalable


Mensajería


Trabajo diferido

Ideal para procesamiento asíncrono


Permite quitar carga del camino online

y agregarlo


RabbitMQ, Redis pub/sub

Escalabilidad entre Clusters


¡Gracias!



https://slid.es/alexfernandez/node-js-produccion


Introducción a node.js en producción

By Alex Fernández

Introducción a node.js en producción

Introducción a Node.js en producción: eventos, callbacks, memoria

  • 5,655