Implementación de funciones de Node.js sin servidor mediante Google Cloud

Publicado: 2022-03-11

Crear software no termina con escribir un buen código. Se completa cuando el software se implementa y es capaz de manejar las solicitudes correctamente y cuando podemos escalar sin obstaculizar el rendimiento y el costo de ejecutarlo.

Probablemente esté pensando en cómo tiene la computación en la nube para encargarse de todas estas cosas. "Entonces, ¿qué es esta nueva cosa sin servidor , Vignes?"

Funciones de Node.js sin servidor con Google Cloud

La computación sin servidor es un estilo de arquitectura en el que el código se ejecuta en una plataforma en la nube donde no tenemos que preocuparnos por la configuración del hardware y el software, la seguridad, el rendimiento y los costos de tiempo de inactividad de la CPU. Es un avance de la computación en la nube que va más allá de la infraestructura y también abstrae el entorno del software. Significa que no se requiere configuración para ejecutar el código.

Con serverless, el siguiente será su estilo de trabajo:

  1. Desarrolle el código.

  2. Cargue el código al proveedor de servicios.

  3. Configure el activador (una solicitud HTTP, en nuestro caso).

¡Nuestro trabajo está hecho! Ahora el proveedor de la plataforma se encargará de las solicitudes entrantes y del escalado.

Introducción a los microservicios sin servidor

La arquitectura sin servidor a menudo se combina con un diseño de estilo de microservicios. Un microservicio es una parte independiente de un gran software que maneja las solicitudes de un módulo específico. Al crear microservicios que pueden ejecutarse en un entorno sin servidor, resulta fácil mantener el código y acelerar las implementaciones.

Introducción a AWS Lambda y GCF, una comparación

Una característica sin servidor a menudo se denomina "back-end como servicio" o "función como servicio". El número de proveedores de computación sin servidor está comenzando a aumentar. Sin embargo, algunos de los grandes jugadores tradicionales también ofrecen opciones sin servidor, como AWS Lambda Functions de Amazon Web Services y Google Cloud Functions (GCF) de Google Cloud, el último de los cuales, aunque actualmente está en versión beta, es lo que estoy usando. Aunque funcionan de manera similar, existen algunas diferencias importantes entre ellos.

AWSLambda Funciones de la nube de Google
Ayuda de idioma Node.js, Python, C#, Java Nodo.js
disparadores DynamoDB, Kinesis, S3, SNS, puerta de enlace API (HTTP), CloudFront y más HTTP, Cloud PubSub, depósito de almacenamiento en la nube
Tiempo máximo de ejecución 300 segundos 540 segundos

En este artículo, repasaremos el proceso de implementación de código sin servidor mediante GCF. Google Cloud Functions es una solución informática asíncrona, liviana y basada en eventos que le permite crear funciones pequeñas con un solo propósito que responden a eventos en la nube sin la necesidad de administrar un servidor o un entorno de tiempo de ejecución.

GCF tiene tres posibles implementaciones separadas en función de los disparadores.

  1. Desencadenador HTTP Enruta las solicitudes HTTP a las funciones de la nube

  2. Disparador interno de publicación/suscripción de Google Enruta las solicitudes de publicación y suscripción a funciones en la nube

  3. Desencadenador del depósito de almacenamiento en la nube Enruta cualquier cambio realizado en el depósito de almacenamiento a la función de la nube

Vamos a crear una configuración basada en activadores HTTP usando Google Cloud Functions

Google Cloud Functions no requiere ninguna configuración o instalación especial adicional. GCF garantiza que el entorno de nodo predeterminado esté configurado y listo para su ejecución. Cuando se crea una función en la nube con HTTP como activador, proporciona una URL para activar la función. En comparación con AWS Lambda, que utiliza una puerta de enlace API como medio para comunicarse con él, Google Cloud Functions proporciona la URL de inmediato según el projectID del proyecto y la región.

Diagrama de Google Cloud Platform: funciones en la nube y AWS Lambda

Creación de una aplicación Node.js sin servidor

Para hacer que nuestro código sea ejecutable en GCF, debemos envolver el código dentro de una sola función. GCF llamará a esa función en particular cada vez que ocurra el disparador. Las formas posibles de hacer esto son cargando,

  1. Archivo único: exporte una función predeterminada que llamará a otras funciones según la solicitud.

  2. Múltiples archivos: tenga un archivo index.js que requiera todos los demás archivos y exporte la función predeterminada como punto de partida.

  3. Múltiples archivos: tenga un archivo principal configurado en package.json usando "main": "main.js" como punto de partida.

Cualquiera de los métodos anteriores funcionará.

GCF tiene una versión de tiempo de ejecución de nodo particular compatible. Asegúrese de que el código esté escrito para admitir esa versión en particular. Al momento de crear esta publicación, GCF es compatible con la versión de Nodo v6.11.1.

Para crear una función, hay pocas opciones a considerar.

  1. Memoria Indica cuánta memoria se necesita para procesar la solicitud durante un tiempo de ejecución. Definido en MB. Para una aplicación pequeña, 128 MB deberían ser suficientes, pero se pueden aumentar hasta 2 GB.

  2. Timeout Timeout, como su nombre lo indica, define el tiempo de espera esperado para la ejecución del código. Después de esto, el código se matará y se detendrá. Cualquier ejecución después de este punto se detendrá abruptamente. El tiempo de espera máximo es de 540 segundos.

  3. Función a ejecutar Aunque se puede exportar más de una función desde el archivo del controlador principal, necesitamos configurar una función que se deba activar para procesar la solicitud. Esto permite que el desarrollador tenga múltiples puntos de entrada basados ​​en el método HTTP/URL.

Para cargar el código, simplemente haga una copia y pegue el código para crear un portal de funciones. Para más de un archivo, comprima el contenido y cargue el archivo. Asegúrese de que, en el caso de un archivo ZIP, debe haber un archivo index.js o un archivo package.json con el archivo principal mencionado.

Cualquier dependencia del módulo NPM debe mencionarse en package.json . GCF intenta instalar los módulos mencionados en el archivo package.json durante la configuración inicial.

Vamos a crear un controlador simple para devolver un estado 200 y algún mensaje. Cree una función y agregue el siguiente código a la fuente.

 exports.httpServer = function httpServer(req, res) { console.log(req); res.status(200).send('Server is working'); } 

Captura de pantalla de la función que se está creando

Una vez creada la función, abra la URL proporcionada para activar la función. Debería responder como lo siguiente.

Captura de pantalla de la salida del navegador "El servidor está funcionando"

Ahora, examinemos el objeto req en los registros. Para ver registros, GCF ofrece opciones directamente desde la consola. Haga clic en los puntos verticales y abra la opción de registros.

Captura de pantalla de la apertura de la opción de registros

Ahora, actualicemos el código para manejar rutas simples para /users .

El siguiente código se usa para manejar una solicitud GET & POST simple para la ruta /users :

 exports.httpServer = function httpServer(req, res) { const path = req.path; switch(path) { case '/users': handleUsers(req, res); break; default: res.status(200).send('Server is working'); } }; const handleUsers = (req, res) => { if (req.method === 'GET') { res.status(200).send('Listing users...'); } else if (req.method === 'POST') { res.status(201).send('Creating User...') } else { res.status(404); } }

Después de actualizar, probémoslo en el navegador ahora, pero esta vez con /users al final.

Captura de pantalla de la salida del navegador "Listado de usuarios..."

Eso es genial. Creamos un servidor HTTP básico con enrutamiento.

Operaciones y depuración

Si el código fuera donde termina la historia, no estaría investigando opciones de infraestructura como aplicaciones Node.js sin servidor. Aquí hay un breve resumen de cómo ocuparse de tareas comunes como la implementación y la depuración. Cosas que los desarrolladores de Node.js ya hacen para otras aplicaciones.

Despliegue:

El código para funciones se puede implementar de cuatro maneras.

  • Copiar pegando el código en la consola

  • Subir un archivo ZIP

  • Implementación desde el depósito de almacenamiento en la nube como un archivo ZIP

  • Implementación desde el repositorio de origen en la nube

La opción más conveniente es, obviamente, implementar desde un repositorio fuente.

Invocación:

Al crear la función, Console proporciona la URL HTTP para activar la función que tiene el formato: https://<region>-<project-id>.cloudfunctions.net/<function-name>

La función de AWS Lambda tiene problemas de inicio en frío que hacen que la ejecución de la función tarde más tiempo en iniciarse. Una vez iniciado, las siguientes ejecuciones responderán con normalidad. Este tiempo de arranque adicional inicial se conoce como arranque en frío. Aunque no tenemos la documentación oficial de GCF relacionada con este tema, los problemas de arranque en frío no aparecieron durante nuestras pruebas.

Depuración:

GCF se integra con el servicio Stackdriver Logging en Google Cloud. Todos los registros y errores de la consola se registrarán aquí y ayuda a depurar el código que ya está implementado.

Pruebas:

La consola proporciona opciones para probar la función pasando un JSON como entrada. La función se llamará con JSON como entrada y la salida se mostrará en la consola. La solicitud (entrada) y la respuesta son similares al marco Express.js y se pueden probar durante el proceso de desarrollo. Si necesita un repaso de las pruebas de Node.js, consulte Una guía de Node.js para realizar pruebas de integración.

Limitaciones y próximos pasos

El uso de funciones sin servidor tiene sus propias ventajas, también viene con limitaciones

  • Bloqueo de proveedores: limita el código que escribimos a un proveedor de servicios en particular. Mover el código a otro proveedor requiere volver a escribir el código con esfuerzos significativos hacia la migración. Como esto puede ser un gran problema, debemos tener mucho cuidado al elegir un proveedor de servicios.

  • Limitaciones en la cantidad de solicitudes y recursos de hardware: los proveedores a menudo limitan la cantidad de solicitudes paralelas que una función manejará a la vez. También hay restricciones de memoria. Estos tipos de restricciones pueden incrementarse hablando con el proveedor, pero seguirán existiendo.

Google Cloud Functions está madurando y mejorando mucho. Todavía se está mejorando y actualizando con frecuencia, especialmente en los idiomas que admite. Si planea usar las funciones de Google Cloud, vigile los registros de cambios para evitar cambios importantes en la implementación.


Lecturas adicionales en el blog de ingeniería de Toptal:

  • Trabajar con compatibilidad con TypeScript y Jest: un tutorial de AWS SAM