Construyendo aplicaciones serverless con AWS y Node.js

Introducción

Con una simple búsqueda en Google podemos descubrir que SERVERLESS significa literalmente, sin servidor, este tipo de arquitecturas sin servidor permiten crear y ejecutar aplicaciones y servicios sin tener que administrar infraestructura.

Los beneficios de no tener que administrar la infraestructura son múltiples: ahorro de costes, escalabilidad automática, mantener el foco en la implementación de las aplicaciones, etc.

También existen algunos inconvenientes: Limitación del tiempo máximo de ejecución de una función, latencias, Stateless development, etc.

Caso Expuesto

Imaginemos que tenemos una aplicación que permite subir imágenes y se nos plantea la funcionalidad de generar thumbnails (tamaño 100×100 y 300×300) de las imágenes que se vayan subiendo.

Podríamos resolver esta funcionalidad con un desarrollo Serverless utilizando la plataforma Amazon AWS y Node.js como tecnología de desarrollo.

Se asume que el lector, cuenta con conocimientos de programación, sistemas operativos Linux y está registrado en Amazon AWS con permisos suficientes (creación de roles, acceso a las funciones lambdas y creación de buckets).

Para empezar crearemos un Bucket de S3 que contendrá al menos la carpeta “images”, en nuestro caso el nombre del bucket es “gigigo-test-lambda”

 

 

 

 

 

 

Para generar los thumbnails, utilizaremos funciones lamba (ejecuta el código como respuesta a eventos y administra automáticamente los recursos). Utilizaremos el método PUT del servicio de S3, para subir nuestra imágen, siendo dicho metódo nuestro evento disparador o TRIGGER de la función lambda , que tendrá como objetivo almacenar los cortes en la carpeta thumbnails.

La función lamba podría estar compuesta por el siguiente código:

 

La función recibiría varios argumentos entre ellos “event” donde vamos a recibir la información del evento que la invoca, por ejemplo las variables (eventRecord.s3.bucket.name o eventRecord.s3.object.key)

La variable crops contiene la informacion de los cortes a generar con su carpeta de destino y propiedades como alto y ancho, etc.

Mediante la librería “aws-sdk” y con el objecto “AWS.S3” utilizando el método “getObject” cogeremos la imágen (conocemos cual es por el evento), generamos los cortes mediante la librería “sharp” y finalmente subiremos los diferentes cortes mediante el método de “putObject”

Para subir nuestra función lambda debemos generar un fichero zip, a continuación podemos crear la función lambda de forma guiada mediante la interfaz de AWS, subiendo el fichero zip correspondiente, puedes encontrar el ejemplo aqui.

 

Además, debemos crear el trigger que asocia S3 (PUT) a nuestra función lambda, indicando correctamente nombre del bucket, carpeta prefix y el tipo de evento.

 

 

Si has seguido todos los pasos y subes un fichero a la carpeta images/ del bucket S3 mediante (PUT), se crearán (si no existen) dos carpetas bajo la carpeta thumbnails, y dentro cada uno de los ficheros con el thumbnail correspondiente.

 

 

Existen otras formas…

El ejemplo anterior es correcto, nuestra función genera los thumbnails respondiendo al evento, aunque como puedes estar pensando es mejorable. Nuestras necesidades podrían cambiar y necesitar cambiar los tamaños de los cortes o crear nuevos cortes adicionales teniendo que modificar la función lamba. Quizá, nos puede interesar subir nuestras imágenes en diferentes buckets, sin modificar o crear triggers adicionales.

Podríamos solucionar dichos problemas invocando la función lamba desde un proyecto nodejs, con un código similar al siguiente:

 

 

Como podéis observar la función lamba de invocada recibe un objeto con la propiedad crops donde se configuran los thumbnails a generar, ademas de las propiedades con el nombre del bucket y del fichero previamente generado.

El código de la función lambda podría ser el siguiente:

 

En nuestro parámetro “event” recibiríamos los datos pasados en la invocación siendo nuestra función lambda más dinámica y flexible.

Podéis encontrar el fichero zip con la función lambda lista para subir aquí.

 

CLAUDIA.JS

Puedes estar pensando que crear formularios en AWS o subir ficheros zip no es algo agradable para desplegar nuestro código. El control de versiones de dichas funciones también puede ser tedioso.

Una de las herramientas que puede solucionar estos problemas es Claudia.js 
Con claudia podemos desplegar fácilmente nuestra función lambda en AWS.

Dado el siguiente repositorio que contiene el código de la última función lambda mencionada anteriormente (deberíamos borrarla si la creamos en el ejemplo anterior, la vamos a crear de nuevo), podríamos desplegar nuestra función lambda de la siguiente forma:

1-Configura las credenciales de aws editando el fichero ~/.aws/credentials

default
aws_access_key_id=YOUR_ACCESS_KEY
aws_secret_access_key=YOUR_SECRET_ACCESS_KEY

 

2-Instala claudia

 

3-Clonamos el repositorio que contiene el código de la función lambda e instalamos paquetería

 

4-Creamos nuestra función lambda en AWS mediante claudia.

De esta forma nuestra función se encontraría desplegada y lista para usarse.

 

5-Si necesitáramos actualizar nuestra función lambda

 

Si no os funciona el ejemplo comprobad que el role generado por claudia tiene permisos para crear recursos en AmazonS3.

 

 

 

 

 

 

Claudia API Builder + Amazon Api Gateway + Lambda

Claudia además de ser una herramienta de despliegue, contiene una librería “API Builder” que nos permite enrutar de manera sencilla nuestras funciones lambda, mediante Amazon API Gateway, pudiendo crear servicios web que utilicen nuestras funciones lambda.

1-Clona el siguiente repositorio, Instala paquetería

 

2-Deploy en AWS

 

3-Después de hacer deploy, aparece un objeto con el resultado, copia el valor de la propiedad url

 

4-Prueba tu servicio de corte de imágenes mediante curl (sustituye url por el valor copiado en el paso anterior)

 

 

Conclusiones

Las arquitecturas SERVERLESS pueden permitir resolver problemas de manera más sencilla al no tener que solucionar posibles problemas de infraestructura. Además pueden ser una buena solución para modelos SAAS donde pueden no tener cabida en infraestructura ciertos desarrollos.

Por otro lado, parece un poco alocado (actualmente) plantearse desarrollos amplios bajo este modelo debido a la falta de flexibilidad que puede presentar (tiempo máximo de ejecución, stateless, latencias).

 

Este post no hubiera sido posible sin la colaboración de:
Mónica, Edu, Manuel, Paco, Jorge Lucas, Nonide y Juan.

Ruby is rubbish! PHP is phpantastic!