Si has estado al día con mi contenido, recordarás que había escrito un artículo titulado, Utilizar AWS Lambda y API Gateway con Node.js y Couchbase NoSQL. En este artículo habíamos explorado el uso de los servicios Serverless de Amazon para crear funciones Lambda que interactúan con Couchbase, nuestra base de datos NoSQL.

Sin embargo, Lambda no es la única tecnología sin servidor, también conocida como funciones como servicio (FaaS). Por ejemplo, Apache OpenWhisk por ejemplo. Con OpenWhisk puede crear funciones de forma similar a como lo haría con Lambda, pero desplegarlas en un conjunto más diverso de ubicaciones, siendo la más popular IBM Bluemix.

Vamos a ver cómo crear funciones sin servidor utilizando OpenWhisk para comunicarnos con nuestro Servidor Couchbase base de datos.

De cara al futuro, hay algunas cosas a tener en cuenta. Necesitarás alojar Couchbase Server en algún lugar accesible por el mundo exterior. Esto significa que tu ordenador local no funcionará. Vas a necesitar Docker para que podamos compilar nuestras dependencias para trabajar con OpenWhisk. Por último, vas a necesitar una cuenta Bluemix, al menos para este ejemplo.

Instalación de las herramientas CLI de Bluemix para OpenWhisk

Como he mencionado anteriormente, OpenWhisk es un proyecto de la Fundación Apache. Sin embargo, por comodidad vamos a utilizarlo en IBM Bluemix.

Crear una cuenta para el Nube de IBM si aún no lo ha hecho.

En lugar de utilizar una herramienta framework como Serverless, vamos a utilizar la CLI de Bluemix. Descarga el CLI de IBM Cloud Functions para que podamos interactuar con OpenWhisk en IBM.

Antes de empezar a trabajar con su cuenta de IBM Cloud, debe iniciar sesión a través de la CLI. Desde la línea de comandos, ejecute lo siguiente:

Al descargar la CLI, se le dará el comando exacto, pero debe ser similar a lo que he presentado anteriormente.

Ahora podemos empezar a crear nuestro proyecto.

Comprender la estructura del proyecto y el proceso de creación de paquetes OpenWhisk

Si nunca has trabajado con FaaS antes, las cosas se hacen un poco diferente a la construcción de una aplicación independiente, difícilmente escalable.

Por ejemplo, cada punto final en nuestro proyecto FaaS será una función separada. Combinadas, estas funciones crean lo que se denomina un paquete. Estas funciones se escalan según sea necesario para satisfacer la demanda cambiante de su aplicación.

Dicho esto, crea lo siguiente:

El proyecto debe tener un directorio para cada función que deseemos crear. Cada función tendrá su propio directorio paquete.json archivo. Cada paquete.json se puede crear ejecutando lo siguiente dentro de cada uno de los directorios:

Dentro de cada uno de los paquete.json también tendrá que definir qué archivo es el código de su función. Por ejemplo, abra crear/paquete.json y añada o cambie la siguiente línea:

Al fijar el principal estamos indicando qué archivo JavaScript contiene nuestra función.

Cuando empecemos a desplegar nuestras funciones, lo haremos para que formen parte del mismo paquete.

Diseñar una función para crear datos

Comencemos el desarrollo con la creación de datos en nuestra base de datos. Navega a la base de datos crear y ejecute el siguiente comando desde la línea de comandos:

El comando anterior instalará nuestras dependencias de funciones. Usaremos el SDK de Couchbase para Node.js, la librería UUID para generar claves únicas, y la librería Joi para validar la entrada.

Volveremos a revisar la instalación de la dependencia, pero al menos nos mantendrá en marcha por ahora.

Ahora abra el proyecto crear/create.js e incluya lo siguiente:

El código anterior es un poco demasiado, así que tenemos que averiguar lo que está pasando. Vamos a empezar con la variable que existe fuera de nuestra función:

No es la mejor idea establecer una nueva conexión cada vez que se llama a la función. En su lugar, podemos mantener una instancia global del Couchbase Bucket abierto y mientras exista, usarlo. Sólo ten en cuenta que no siempre existirá porque OpenWhisk destruirá las funciones después de un tiempo de inactividad.

Dentro de nuestra función comprobamos si el Bucket ya está abierto. Si el Bucket no está abierto, establecemos una conexión utilizando los parámetros pasados a la función. Cuando llegue el momento, definiremos parámetros por defecto que contengan esta información de conexión.

Como estamos creando datos, necesitamos validar que la entrada es correcta.

Esperamos un nombre y apellido esté presente. También esperamos un tipo no esté presente. Podemos validar esto con lo siguiente:

En stripUnknown eliminará los datos no definidos en el esquema. Necesitamos eliminar datos porque nuestra información de entrada y de conexión existirá en la misma carga útil. No queremos que la información de conexión se guarde en nuestros documentos. Si hay un error de validación, será devuelto. Si no hubo error de validación, podemos proceder a insertar los datos.

Podemos generar una nueva clave única y guardar los datos validados como un documento. Los propios datos se devolverán como respuesta.

Las demás funciones seguirán esta misma estrategia, más o menos.

Diseño de una Función para Recuperar Datos con N1QL

Ahora que tenemos los datos, vamos a intentar recuperarlos de la base de datos con una invocación a una función. Navega a tu recuperar y ejecute lo siguiente desde la línea de comandos:

Como no vamos a crear datos, no necesitamos generar valores únicos ni validar ningún dato de usuario. Por esta razón, sólo necesitamos el SDK de Couchbase para esta función.

Abra el archivo recuperar/retrieve.js e incluya lo siguiente:

Vamos a saltar sobre lo que ya hemos visto en la función anterior y saltar a lo que es nuevo. Una vez que estamos conectados a un Bucket abierto, podemos crear una consulta N1QL.

Esta consulta N1QL es de tipo SQL y nos permitirá recuperar todos los documentos que coincidan con ciertos criterios. Si hay algún error, lo devuelve como respuesta, en caso contrario devuelve el conjunto de resultados.

Como no estamos validando nada, esta función para recuperar datos era mucho más sencilla.

Diseño de una función para actualizar datos con mutaciones de subdocumentos

Supongamos ahora que queremos actualizar documentos dentro de la base de datos. En lugar de recuperar documentos, hacer cambios y luego guardar esos cambios, vamos a enviar los cambios directamente a la base de datos y dejar que la base de datos resuelva las cosas.

Navegue hasta la sección actualización y ejecute lo siguiente desde la línea de comandos:

Como estamos aceptando datos de usuarios, queremos validar esos datos. No estamos creando datos, por lo que no necesitamos generar claves únicas.

Abra el archivo actualizar/update.js e incluya lo siguiente:

¿Le resulta familiar el código anterior? Debería, porque seguimos la misma estrategia.

Nuestra lógica de validación es ligeramente diferente en este ejemplo:

Queremos editar un documento en particular por lo que se requiere una clave. No sabemos lo que el usuario quiere actualizar así que establecemos las propiedades como opcionales.

Para hacer actualizaciones vamos a hacer operaciones de subdocumento en nuestros documentos. Para ello, podemos utilizar un constructor de mutación.

Proporcionamos un documento para alterar y las rutas en las que existen las propiedades. Las rutas pueden ser mucho más complejas que los ejemplos utilizados aquí.

Con el conjunto de mutaciones definido, podemos ejecutarlas contra la base de datos.

Dependiendo del resultado, se devolverá una respuesta de la invocación de la función.

Diseñar una función para eliminar datos

Estamos en la última función de un paquete de operaciones CRUD. Ha llegado el momento de eliminar datos de la base de datos.

Navegue hasta el borrar y ejecute el siguiente comando:

Estaremos aceptando claves de documentos para ser borrados por lo que necesitaremos validar la entrada. Del mismo modo también necesitamos el SDK de Couchbase para trabajar con la base de datos.

Abra el archivo delete/delete.js e incluya el siguiente código JavaScript:

Probablemente estás viendo el panorama general ahora en lo que respecta a la creación de funciones con OpenWhisk y Couchbase, por lo que no vamos a caminar a través de la función anterior para eliminar documentos.

Empaquetado y despliegue de las funciones en OpenWhisk con Docker

Tenemos un conjunto de funciones listas, pero no podemos empaquetarlas y desplegarlas en Bluemix. Si lo hiciéramos, obtendríamos un montón de errores. Bluemix utiliza un sabor especial de Linux con una arquitectura determinada. He descargado las dependencias en mi Mac que no es compatible.

¿Recuerdas el artículo que escribí hace un tiempo titulado, Implementación de dependencias de Node.js nativo en AWS Lambda? Necesitamos hacer algo similar para OpenWhisk con Docker.

Con Docker instalado y listo para funcionar, ejecute lo siguiente desde la CLI:

Los comandos anteriores descargarán una imagen Docker OpenWhisk apropiada para Node.js. Luego desplegaremos un contenedor con esa imagen en modo terminal interactivo. Este contenedor también tendrá un volumen mapeado. Estoy mapeando mi directorio local del proyecto a un directorio dentro del contenedor.

Después de que el comando se haya ejecutado y el contenedor se haya desplegado, deberías estar en el shell dentro del contenedor.

Para cada función, ejecute lo siguiente:

Recuerda, instalar las dependencias desde nuestra máquina anfitriona no es suficiente. Necesitamos compilar las dependencias para Bluemix. Docker compilará estas dependencias y como el directorio está mapeado, podemos utilizarlas desde la máquina anfitriona.

Una vez instalados los paquetes de cada función, podemos empaquetarlos y desplegarlos.

Desde la máquina anfitriona, cree un archivo ZIP de cada una de las funciones. El archivo debe contener paquete.json el archivo JavaScript y el archivo node_modules directorio.

Si estás en un Mac o en un ordenador con ZIP CLI, ejecuta lo siguiente:

Cuando tengas un ZIP de cada función, se pueden desplegar ejecutando lo siguiente:

He introducido algunas cosas nuevas en el comando anterior.

En primer lugar, vamos a crear un paquete llamado couchbase y en este paquete tenemos un borrar basada en la función borrar.zip archivo. También estoy pasando algunos parámetros por defecto. Estos parámetros serán nuestra información de conexión. Como esta información es sensible, no los estamos pasando al invocar la función, sino al crear la función.

Ejecute una variación del comando anterior para cada una de sus funciones.

Para ejecutar su función, intente ejecutar algo como lo siguiente:

El comando anterior debe pasar algunos parámetros para pasar la validación. La función se invoca de forma bloqueante, y si tiene éxito, nuestros datos se guardarán en la base de datos y se devolverán en la respuesta.

Conclusión

Acabas de ver cómo crear un paquete de funciones sin servidor para OpenWhisk que se comunican con la base de datos NoSQL, Couchbase. OpenWhisk puede utilizarse como alternativa a AWS Lambda, pero no son las únicas opciones disponibles. Independientemente de lo que elijas, las funciones como servicio (FaaS) son soluciones muy escalables para aplicaciones masivas.

¿Quieres ver otro ejemplo de OpenWhisk? Echa un vistazo a un tutorial que escribí titulado, Convierte una API RESTful de Node.js a Serverless con OpenWhisk.

Autor

Publicado por Nic Raboy, Defensor del Desarrollador, Couchbase

Nic Raboy es un defensor de las tecnologías modernas de desarrollo web y móvil. Tiene experiencia en Java, JavaScript, Golang y una variedad de frameworks como Angular, NativeScript y Apache Cordova. Nic escribe sobre sus experiencias de desarrollo relacionadas con hacer el desarrollo web y móvil más fácil de entender.

3 Comentarios

  1. Hola 👋 Nick gran post
    Hoy he aprendido algo nuevo sobre el paquete joi 👍🏼

    Algunos consejos
    Puedes hacer que tus acciones sean una acción web y tengan una url pública cuando creas -web true

    También puede omitir JSON.stringify y establecer el cuerpo a un objeto que se stringify para usted.

    Para obtener la url pública de la acción web puedes ejecutar wsk action get couchbase/delete -url

    Puede obtener más información sobre el uso de acciones web en la documentación aquí https://console.bluemix.net/docs/openwhisk/openwhisk_webactions.html

Dejar una respuesta