Diferencia entre revisiones de «Node.js y MongoDB»
(Página creada con «= Node.js = == Introducción a Node.js == [http://nodejs.org/ Node.js] es un entorno '''JavaScript de lado de servidor''' que utiliza un '''modelo asíncrono''' y '''dirig…») |
(→Ejecución asíncrona sin bloqueo) |
||
(No se muestran 5 ediciones intermedias del mismo usuario) | |||
Línea 8: | Línea 8: | ||
No olvidemos que V8 es actualizado constantemente y es uno de los intérpretes más rápidos que puedan existir en la actualidad para cualquier lenguaje dinámico. Además las capacidades de Node para I/O (Entrada/Salida) son realmente ligeras y potentes, dando al desarrollador la posibilidad de utilizar a tope la I/O del sistema. Node soporta protocolos TCP, DNS y HTTP. | No olvidemos que V8 es actualizado constantemente y es uno de los intérpretes más rápidos que puedan existir en la actualidad para cualquier lenguaje dinámico. Además las capacidades de Node para I/O (Entrada/Salida) son realmente ligeras y potentes, dando al desarrollador la posibilidad de utilizar a tope la I/O del sistema. Node soporta protocolos TCP, DNS y HTTP. | ||
+ | Una de las cosas más importantes por las que la gente se confunde cuando se explica Node.js es entender qué es exactamente. ¿Es un lenguaje diferente? ¿es solo un framework por encima o es algo más? | ||
− | + | Node.js definitivamente no es un nuevo lenguaje, y no es solo un framework de JavaScript. Puede ser considerado como un entorno de tiempo de ejecución para JavaScript construido sobre el motor V8 de Google. | |
− | + | Entonces, nos proporciona un contexto donde podemos escribir código JavaScript en cualquier plataforma donde se puede instalar Node.js. ¡En cualquier sitio! | |
− | + | ||
− | + | Ahora un poco sobre su historia! En 2009, Ryan Dahl hizo una presentación en JSConf eso cambió JavaScript para siempre. Durante su presentación, presentó a Node.js La comunidad JavaScript. Después de una charla de aproximadamente 45 minutos, concluyó, recibiendo una gran ovación de la audiencia en el proceso. Se inspiró para escribir Node.js después de ver una barra de progreso de carga de archivos simple en Flickr, el sitio para compartir imágenes. | |
− | + | ||
− | + | Al darse cuenta de que el sitio estaba realizando todo el proceso de manera incorrecta, él decidió que tenía que haber una mejor solución. | |
+ | |||
+ | Ahora veamos las características de Node.js, que lo hace único de otros lenguajes de programación del lado del servidor. | ||
+ | |||
+ | |||
+ | === La ventaja que aporta el motor V8 de Google === | ||
+ | |||
+ | El motor V8 fue desarrollado por Google y fue de código abierto en 2008. JavaScript es un lenguaje interpretado y no será tan eficiente como un lenguaje compilado, ya que cada línea de código se interpreta una por una mientras el código se ejecuta. | ||
+ | |||
+ | El motor V8 trae un modelo eficiente aquí, donde el código de JavaScript se compilará en código de nivel de máquina y las ejecuciones sucederán en el código compilado en lugar de interpretar el JavaScript. Pero a pesar de que NodeJS está utilizando el motor V8, Joyent, que es la compañía que mantiene NodeJS, no siempre actualiza el motor V8 a las últimas versiones que Google lanza activamente. Esto ha llevado a la nueva variante llamada io.js. | ||
+ | |||
+ | === Node.js mantiene un único subproceso === | ||
+ | |||
+ | Tal vez se pregunte, ¿cómo ayuda un modelo de subproceso único? | ||
+ | |||
+ | Típicamente PHP, ASP.Los servidores NET, Ruby o basados en Java siguen un modelo donde cada cliente solicita resultados con la instanciación de un nuevo hilo o incluso un proceso. Cuando se trata de Node.js, las solicitudes se ejecutan en el mismo hilo, incluso con recursos compartidos. | ||
− | + | ¿Cuál será la ventaja de usar ese modelo de hilo único? | |
− | + | Primero debemos entender el problema que Node.js intenta resolver. Intenta hacer procesamiento asíncrono en un solo hilo para proporcionar más rendimiento y escalabilidad para aplicaciones que supuestamente manejan demasiado tráfico web. | |
− | + | Imagine aplicaciones web que manejan millones de solicitudes concurrentes; si el servidor crea un nuevo hilo para manejar cada solicitud que llega, consumirá muchos recursos y terminaríamos intentando agregar más y más servidores para aumentar la escalabilidad de la aplicación. El modelo de procesamiento asíncrono de subproceso único, tiene su ventaja en el contexto anterior, y puede procesar muchas más solicitudes concurrentes con menos cantidad de recursos del lado del servidor. Sin embargo, hay un desventaja de este enfoque: el nodo (por defecto) no utilizará la cantidad de CPU cores disponibles en el servidor en el que se ejecuta, sin utilizar módulos adicionales como pm2. | |
− | + | === Ejecución asíncrona sin bloqueo === | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Una de las características más poderosas de NodeJs es que está dirigido por eventos y asíncrono. Entonces, ¿cómo funciona un modelo asincrónico? | |
− | + | Imagina que tienes un bloque de código y en alguna enésima línea tiene una operación que requiere mucho tiempo. | |
− | + | Y qué sucede con las líneas que siguen a la enésima línea mientras se ejecuta este código? En modelos de programación síncrona, las líneas que siguen a la enésima línea tendrán que esperar hasta que se complete la operación en esa línea. Un modelo asincrónico maneja este caso de forma distinta. Para gestionar este escenario en un enfoque asincrónico, necesitamos segmentar el código que sigue a la enésima línea en dos secciones: la primera sección es | |
− | + | dependiente del resultado de la operación en la enésima línea y la segunda sección es independiente del resultado. | |
− | + | Envolvemos el código dependiente en una función con el resultado de la operación como su parámetro y lo registramos como una función de retorno (callback) que se llamará cuando terminó con éxito la operación. Una vez la operación está completa, la función de devolución de llamada se activará con su resultado. Mientras tanto, podemos continuar ejecutando las líneas independientes del resultado sin esperar el resultado. | |
− | |||
− | |||
− | + | En este escenario, la ejecución nunca se bloquea para que se complete un proceso. Solo va con funciones de devolución de llamada registradas en cada finalización. En pocas palabras, usted asigna una función de devolución de llamada a una operación, y cuando NodeJS determina que ha finalizado la tarea, se activa el evento, y ejecutará su función de devolución de llamada en ese momento. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Para entenderlo veamos un ejemplo de asincronía en detalle: | |
+ | <source lang="bash"> | ||
− | |||
− | + | console.log('Uno'); | |
+ | console.log('Dos'); | ||
+ | setTimeout(function() { | ||
+ | console.log('Tres'); | ||
+ | }, 2000); | ||
+ | console.log('Cuatro'); | ||
+ | console.log('Cinco'); | ||
− | + | # En una llamada típica síncrona el código anterior devolvería: | |
− | + | Uno | |
+ | Dos | ||
+ | ... (2 segundos de espera) ... | ||
+ | Tres | ||
+ | Cuatro | ||
+ | Cinco | ||
− | + | # Sin embargo en una llamada asíncrona, el resultado sería: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Uno | |
+ | Dos | ||
+ | Cuatro | ||
+ | Cinco | ||
+ | ... (approx. 2 segundos de espera) ... | ||
+ | Tres | ||
− | + | # La función que actualmente muestra "Tres" y que está asignada al TimeOut se denomina función de callback o retorno. | |
− | + | </source> | |
− | |||
− | |||
− | + | === ¿Qué diferencias tiene Node.js respecto a Apache u otros servidores web? === | |
− | + | * Apache crea un nuevo hilo por cada conexión cliente-servidor. Esto funciona bien para pocas conexiones, pero crear nuevos hilos tiene un coste, así como la realización de cambios de contexto. A partir de 400 conexiones simultáneas, el número de segundos para atender las peticiones crece considerablemente. Podemos decir que Apache funciona bien pero no es el mejor servidor para lograr máxima concurrencia (lograr tener el número mayor de conexiones abiertas posibles). | |
+ | * Uno de los puntos fuertes de Node es su capacidad de mantener muchas conexiones abiertas y esperando. En Apache por ejemplo el parámetro '''MaxClients por defecto es 256'''. Este valor puede ser aumentado para servir contenido estático, sin embargo si se sirven aplicaciones web dinámicas en PHP u otro lenguaje es probable que al poner un valor alto el servidor se quede bloqueado ante muchas conexiones -esto dependerá del trabajo que la aplicación web de al servidor y de su capacidad hardware-. | ||
+ | * Una aplicación para Node se programa sobre un solo hilo. Si en la aplicación existe una operación bloqueante (entrada/salida por ejemplo), Node creará entonces otro hilo en segundo plano, pero no lo hará sistemáticamente por cada conexión como haría Apache. | ||
+ | * En teoría Node puede mantener tantas conexiones como número máximo de archivos descriptores (sockets) soportados por el sistema. En un sistema UNIX este límite puede rondar por las '''65.000 conexiones''', un número muy alto. Sin embargo en la realidad la cifra depende de muchos factores, como la cantidad de información que esté la aplicación distribuyendo a los clientes. | ||
+ | * Una aplicación con actividad normal podría mantener '''20.000-25.000''' clientes a la vez sin haber apenas retardo en las respuestas. Un inconveniente de Node es que debido a su arquitectura (de usar sólo un hilo) también sólo podrá usar una CPU. Un método para usar múltiples núcleos sería iniciar múltiples instancias de Node en el servidor y poner un balanceador de carga delante de ellos. | ||
− | + | Node.js no es el único servidor de este tipo, hay otros proyectos como Tornado (Python), Twisted(Python),Apache Mina(Java), Jetty(Java), etc. | |
− | |||
− | |||
− | |||
− | |||
− | + | Otra buena alternativa puede ser el lenguaje [http://www.erlang.org/ Erlang] el cuál permite crear sistemas en tiempo real con alta escalabilidad y alta disponibilidad. | |
= Instalacion de Node.js y npm (node packet manager) en Debian = | = Instalacion de Node.js y npm (node packet manager) en Debian = | ||
Línea 193: | Línea 203: | ||
var http = require('http'); | var http = require('http'); | ||
− | http.createServer(function (request, response) { | + | http.createServer(function (request, response) |
− | response.writeHead(200, {'Content-Type': 'text/html'}); | + | { |
− | response.end('Funciona mi servidor con Node.js!'); | + | response.writeHead(200, {'Content-Type': 'text/html'}); |
+ | response.end('Funciona mi servidor con Node.js!'); | ||
}).listen(8080); | }).listen(8080); | ||
Revisión del 11:15 4 dic 2019
Sumario
Node.js
Introducción a Node.js
Node.js es un entorno JavaScript de lado de servidor que utiliza un modelo asíncrono y dirigido por eventos.
Node usa el motor de JavaScript V8 de Google: una VM tremendamente rápida y de gran calidad escrita por gente como Lars Bak, uno de los mejores ingenieros del mundo especializados en VMs.
No olvidemos que V8 es actualizado constantemente y es uno de los intérpretes más rápidos que puedan existir en la actualidad para cualquier lenguaje dinámico. Además las capacidades de Node para I/O (Entrada/Salida) son realmente ligeras y potentes, dando al desarrollador la posibilidad de utilizar a tope la I/O del sistema. Node soporta protocolos TCP, DNS y HTTP.
Una de las cosas más importantes por las que la gente se confunde cuando se explica Node.js es entender qué es exactamente. ¿Es un lenguaje diferente? ¿es solo un framework por encima o es algo más?
Node.js definitivamente no es un nuevo lenguaje, y no es solo un framework de JavaScript. Puede ser considerado como un entorno de tiempo de ejecución para JavaScript construido sobre el motor V8 de Google.
Entonces, nos proporciona un contexto donde podemos escribir código JavaScript en cualquier plataforma donde se puede instalar Node.js. ¡En cualquier sitio!
Ahora un poco sobre su historia! En 2009, Ryan Dahl hizo una presentación en JSConf eso cambió JavaScript para siempre. Durante su presentación, presentó a Node.js La comunidad JavaScript. Después de una charla de aproximadamente 45 minutos, concluyó, recibiendo una gran ovación de la audiencia en el proceso. Se inspiró para escribir Node.js después de ver una barra de progreso de carga de archivos simple en Flickr, el sitio para compartir imágenes.
Al darse cuenta de que el sitio estaba realizando todo el proceso de manera incorrecta, él decidió que tenía que haber una mejor solución.
Ahora veamos las características de Node.js, que lo hace único de otros lenguajes de programación del lado del servidor.
La ventaja que aporta el motor V8 de Google
El motor V8 fue desarrollado por Google y fue de código abierto en 2008. JavaScript es un lenguaje interpretado y no será tan eficiente como un lenguaje compilado, ya que cada línea de código se interpreta una por una mientras el código se ejecuta.
El motor V8 trae un modelo eficiente aquí, donde el código de JavaScript se compilará en código de nivel de máquina y las ejecuciones sucederán en el código compilado en lugar de interpretar el JavaScript. Pero a pesar de que NodeJS está utilizando el motor V8, Joyent, que es la compañía que mantiene NodeJS, no siempre actualiza el motor V8 a las últimas versiones que Google lanza activamente. Esto ha llevado a la nueva variante llamada io.js.
Node.js mantiene un único subproceso
Tal vez se pregunte, ¿cómo ayuda un modelo de subproceso único?
Típicamente PHP, ASP.Los servidores NET, Ruby o basados en Java siguen un modelo donde cada cliente solicita resultados con la instanciación de un nuevo hilo o incluso un proceso. Cuando se trata de Node.js, las solicitudes se ejecutan en el mismo hilo, incluso con recursos compartidos.
¿Cuál será la ventaja de usar ese modelo de hilo único?
Primero debemos entender el problema que Node.js intenta resolver. Intenta hacer procesamiento asíncrono en un solo hilo para proporcionar más rendimiento y escalabilidad para aplicaciones que supuestamente manejan demasiado tráfico web.
Imagine aplicaciones web que manejan millones de solicitudes concurrentes; si el servidor crea un nuevo hilo para manejar cada solicitud que llega, consumirá muchos recursos y terminaríamos intentando agregar más y más servidores para aumentar la escalabilidad de la aplicación. El modelo de procesamiento asíncrono de subproceso único, tiene su ventaja en el contexto anterior, y puede procesar muchas más solicitudes concurrentes con menos cantidad de recursos del lado del servidor. Sin embargo, hay un desventaja de este enfoque: el nodo (por defecto) no utilizará la cantidad de CPU cores disponibles en el servidor en el que se ejecuta, sin utilizar módulos adicionales como pm2.
Ejecución asíncrona sin bloqueo
Una de las características más poderosas de NodeJs es que está dirigido por eventos y asíncrono. Entonces, ¿cómo funciona un modelo asincrónico?
Imagina que tienes un bloque de código y en alguna enésima línea tiene una operación que requiere mucho tiempo.
Y qué sucede con las líneas que siguen a la enésima línea mientras se ejecuta este código? En modelos de programación síncrona, las líneas que siguen a la enésima línea tendrán que esperar hasta que se complete la operación en esa línea. Un modelo asincrónico maneja este caso de forma distinta. Para gestionar este escenario en un enfoque asincrónico, necesitamos segmentar el código que sigue a la enésima línea en dos secciones: la primera sección es dependiente del resultado de la operación en la enésima línea y la segunda sección es independiente del resultado.
Envolvemos el código dependiente en una función con el resultado de la operación como su parámetro y lo registramos como una función de retorno (callback) que se llamará cuando terminó con éxito la operación. Una vez la operación está completa, la función de devolución de llamada se activará con su resultado. Mientras tanto, podemos continuar ejecutando las líneas independientes del resultado sin esperar el resultado.
En este escenario, la ejecución nunca se bloquea para que se complete un proceso. Solo va con funciones de devolución de llamada registradas en cada finalización. En pocas palabras, usted asigna una función de devolución de llamada a una operación, y cuando NodeJS determina que ha finalizado la tarea, se activa el evento, y ejecutará su función de devolución de llamada en ese momento.
Para entenderlo veamos un ejemplo de asincronía en detalle:
console.log('Uno');
console.log('Dos');
setTimeout(function() {
console.log('Tres');
}, 2000);
console.log('Cuatro');
console.log('Cinco');
# En una llamada típica síncrona el código anterior devolvería:
Uno
Dos
... (2 segundos de espera) ...
Tres
Cuatro
Cinco
# Sin embargo en una llamada asíncrona, el resultado sería:
Uno
Dos
Cuatro
Cinco
... (approx. 2 segundos de espera) ...
Tres
# La función que actualmente muestra "Tres" y que está asignada al TimeOut se denomina función de callback o retorno.
¿Qué diferencias tiene Node.js respecto a Apache u otros servidores web?
- Apache crea un nuevo hilo por cada conexión cliente-servidor. Esto funciona bien para pocas conexiones, pero crear nuevos hilos tiene un coste, así como la realización de cambios de contexto. A partir de 400 conexiones simultáneas, el número de segundos para atender las peticiones crece considerablemente. Podemos decir que Apache funciona bien pero no es el mejor servidor para lograr máxima concurrencia (lograr tener el número mayor de conexiones abiertas posibles).
- Uno de los puntos fuertes de Node es su capacidad de mantener muchas conexiones abiertas y esperando. En Apache por ejemplo el parámetro MaxClients por defecto es 256. Este valor puede ser aumentado para servir contenido estático, sin embargo si se sirven aplicaciones web dinámicas en PHP u otro lenguaje es probable que al poner un valor alto el servidor se quede bloqueado ante muchas conexiones -esto dependerá del trabajo que la aplicación web de al servidor y de su capacidad hardware-.
- Una aplicación para Node se programa sobre un solo hilo. Si en la aplicación existe una operación bloqueante (entrada/salida por ejemplo), Node creará entonces otro hilo en segundo plano, pero no lo hará sistemáticamente por cada conexión como haría Apache.
- En teoría Node puede mantener tantas conexiones como número máximo de archivos descriptores (sockets) soportados por el sistema. En un sistema UNIX este límite puede rondar por las 65.000 conexiones, un número muy alto. Sin embargo en la realidad la cifra depende de muchos factores, como la cantidad de información que esté la aplicación distribuyendo a los clientes.
- Una aplicación con actividad normal podría mantener 20.000-25.000 clientes a la vez sin haber apenas retardo en las respuestas. Un inconveniente de Node es que debido a su arquitectura (de usar sólo un hilo) también sólo podrá usar una CPU. Un método para usar múltiples núcleos sería iniciar múltiples instancias de Node en el servidor y poner un balanceador de carga delante de ellos.
Node.js no es el único servidor de este tipo, hay otros proyectos como Tornado (Python), Twisted(Python),Apache Mina(Java), Jetty(Java), etc.
Otra buena alternativa puede ser el lenguaje Erlang el cuál permite crear sistemas en tiempo real con alta escalabilidad y alta disponibilidad.
Instalacion de Node.js y npm (node packet manager) en Debian
Veamos como realizar la instalación de Node.js y el gestor de paquetes de Node npm.
Instalación de Node.js en Debian
Para instalar la última versión de Nodejs haremos lo siguiente:
curl -sL https://deb.nodesource.com/setup_13.x | sudo bash -
# Instalamos a continuación nodejs y npm
apt-get install -y nodejs
# Chequeamos la versión instalada:
node -v
v13.2.0
Comandos básicos en el uso de Node.js
Desde la línea de comandos de node podemos teclear instrucciones para ejecutar aplicaciones o bien escribir una aplicación. En general lo que se suele hacer es crear un fichero .js con las instrucciones de la aplicación que va a ejecutar Node.
El entorno de trabajo al que se accede desde la línea de comandos se denomina REPL.
// Para acceder a la línea de comandos REPL de node:
node
// Accederemos a la consola de trabajo indicada con el símbolo >
// Para consultar ayuda de node:
> .help
// Para salir de node:
> .exit
// O bien CTRL+C CTRL+C
// Ejemplo de código de javascript en el entorno REPL de node:
>a=4;
4
// Ejemplo de pequeño programa en linea de comandos >:
> a=[1,2,3];
> a.forEach(function(valor){
..... console.log(valor);
..... });
// Producirá como resultado
1
2
3
Ejemplo de video con comandos de prueba en el entorno REPL de Node:
Creación de un servidor web en Nodejs
Una de las grandes ventajas de Nodejs es su simplicidad. A diferencia de PHP o ASP en NodeJS no hay separación entre el servidor web y el propio código de la aplicación, ni tampoco tenemos que editar grandes ficheros de configuración para definir un comportamiento concreto. Con Node creamos el servidor, lo configuramos y entregamos el contenido y todo a nivel de código.
Vamos a ver cómo crear un servidor web con Node y enviar contenido a través de él, con seguridad y eficiencia.
Ajustando las rutas
Para poder enviar contenido web necesitamos crear una URI (Universal Resource Identifier) que identifique el recurso al que queremos acceder. En otras palabras crear las diferentes rutas de la aplciación que mostrarán las diferentes páginas o contenidos de la web.
Lo primero que haremos será crear nuestro fichero de servidor. Por ejemplo le llamamos server.js
El proceso consistiría en:
- Escribir todo el código del servidor web y de nuestra aplicación dentro del fichero server.js.
- Guardar el fichero server.js
- Arrancar la aplicación con el comando: node server.js
- Y así una y otra vez, cada vez que hagamos modificaciones en el fichero.
Para evitar el tener que ejecutar el comando: node server.js cada vez que modifiquemos la aplicación, podemos utilizar una aplicación adicional llamada hotnode, que se encargará de reiniciar nuestra aplicación cada vez que modifiquemos el fichero server.js.
Instalamos hotnode de forma global, para utilizarlo más adelante con nuestro server:
# Instalamos hotnode globalmente
npm -g install hotnode
# Para ejecutar el servidor:
hotnode server.js
# Hotnode auto-reiniciará nuestro servidor cada vez que grabemos las modificaciones en el fichero.
Para crear el servidor web necesitamos un módulo denominado http, que instalaremos dentro de la carpeta dónde tendremos nuestro servidor:
# Instalamos el módulo http:
npm install http
# Código que va dentro del fichero server.js:
var http = require('http');
http.createServer(function (request, response)
{
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('Funciona mi servidor con Node.js!');
}).listen(8080);
# Si estamos utilizando el VPS de Google tendremos que abrir en el firewall el puerto 8080 para permitir dicho tráfico al servidor:
# Lo haremos en:
Google Cloud Platform -> Red de VPC -> Reglas de cortafuegos
# Agregaremos una regla:
# Nombre: nodejs
# Descripción: Para acceder al servidor de Node en 8080
# Destinos: Todas las instancias de la red
# Intervalos de IPs de origen: 0.0.0.0/0
# Protocolos y puertos:
# tcp: 8080
# Pulsamos el boton Crear.
# Para comprobar si funciona nuestro servidor web, nos tendremos que conectar a nuestro dominio pero al puerto 8080.
# Por ejemplo:
http://veiga.dynu.net:8080/
# Y se mostrará el mensaje:
Funciona mi servidor con Node.js!