Desarrollo de aplicaciones Python sin servidor con AWS Chalice

En el desarrollo de software, constantemente creamos soluciones para usuarios finales que resuelven un problema en particular o facilitan/automatizan un determinado proceso. Por lo tanto, des...

Introducción

En el desarrollo de software, constantemente creamos soluciones para usuarios finales que resuelven un problema en particular o facilitan/automatizan un determinado proceso. Por lo tanto, diseñar y construir el software no es la única parte del proceso, ya que tenemos que poner el software a disposición de los usuarios previstos.

Para las aplicaciones basadas en la web, la implementación es un aspecto muy importante y parte del proceso, ya que la aplicación no solo debe funcionar, sino que también debe funcionar para muchos usuarios al mismo tiempo y tener una alta disponibilidad.

Algunas de las opciones de implementación que tenemos disponibles incluyen la compra de nuestro propio hardware de servidor y la implementación de nuestras aplicaciones o el alquiler de espacio de servidor en otras empresas. Esto tiene un costo no solo de los recursos necesarios para adquirirlos, sino también de los costos de mantenimiento y del personal para monitorear los recursos del servidor.

¿Qué pasaría si pudiéramos hacer que nuestra aplicación esté disponible sin tener que preocuparnos por aprovisionar servidores o mantenerlos? Nuestra agilidad y entrega mejorarían enormemente.

Podemos lograr esto a través de una plataforma informática sin servidor como AWSLambda, que está disponible a través de [Servicios web de Amazon](https://aws.amazon .com/).

¿Qué es la informática sin servidor?

Los proveedores de la nube ofrecen diferentes soluciones para implementar y ejecutar aplicaciones, una de ellas es la informática sin servidor. En esta arquitectura, el proveedor de la nube aloja sus aplicaciones y asume las responsabilidades de la gestión del servidor en términos de software y hardware. Piense en ello como Infraestructura como servicio (IaaS).

El proveedor de la nube maneja el escalado, la disponibilidad, el mantenimiento del servidor y la configuración, entre otras cosas, de modo que, como desarrolladores, nuestro enfoque está completamente en nuestro código. Esto, a su vez, reduce los gastos generales necesarios para que nuestras aplicaciones se ejecuten y estén disponibles para nuestros usuarios finales.

La informática sin servidor tiene sus ventajas, pero también presenta algunos inconvenientes, como que el desarrollador está limitado a las opciones o herramientas que el proveedor utiliza para fines como el registro, el seguimiento y la supervisión, y el desarrollador no puede utilizar sus propias herramientas. Además, como desarrollador, está atado a la disponibilidad del proveedor, si experimentan problemas o interrupciones, nuestra aplicación también se ve afectada.

AWS es un proveedor líder en la nube que ofrece computación sin servidor a través de AWS Lambda. Este es un tiempo de ejecución de cómputo sin servidor que permite a los desarrolladores ejecutar su código en respuesta a ciertos eventos de los usuarios, como realizar una solicitud o cargar archivos en un [cubeta S3] (https://aws.amazon.com/s3/).

Este servicio también nos permite pagar solo por los recursos informáticos que utilizamos en lugar de un costo general por los servicios. Esto sucede a través de una función Lambda que escala para coincidir con la escala y es independiente de la infraestructura subyacente.

¿Qué es el cáliz?

Cáliz es un microframework para construir e implementar rápidamente aplicaciones serverless en Python para funciones de AWS Lambda. Chalice no solo nos ayuda a crear aplicaciones de Python, sino también a implementarlas rápidamente al proporcionar una herramienta de línea de comandos para crear, administrar e implementar nuestra aplicación.

Chalice también proporciona funcionalidad de integración con otros servicios de Amazon, como Amazon API Gateway, Amazon Simple Storage Service (S3) y Simple Queue Service (SQS), entre otros. Podemos crear API RESTful, tareas que se ejecutan en un horario determinado o integrarse al depósito S3 para el almacenamiento.

Configuración

Configuración de AWS

Para comenzar con Chalice, debemos tener una cuenta de AWS configurada para interactuar e implementar nuestro código. Esto se puede lograr a través de la página de inicio de AWS donde podemos registrarnos o iniciar sesión en una cuenta de AWS existente. AWS requiere que no solo ofrezcamos nuestros datos sino también nuestros datos de facturación, pero para esta demostración utilizaremos la Capa gratuita de AWS con fines de prueba y desarrollo. por lo que no se nos facturará.

Una vez que nuestra cuenta está configurada, en el menú desplegable de nuestro perfil, hay una sección llamada "Mis credenciales de seguridad". Aquí podremos crear credenciales que se utilizarán al interactuar con la consola de AWS. Estas credenciales también serán utilizadas por la herramienta CLI de Amazon.

Amazon también ofrece una herramienta CLI que podemos usar para interactuar con nuestros servicios de AWS usando comandos en nuestra terminal. Está disponible para plataformas Mac, Linux y Windows y requiere Python 2.6+ o Python 3.3 o una versión posterior. Podemos instalarlo ejecutando el siguiente comando pip:

1
$ pip install awscli

Una vez configurada, podemos probar la herramienta CLI ejecutando:

1
$ aws --version

Se pueden encontrar más detalles sobre la herramienta CLI y la instalación en otras plataformas aquí.

Con la configuración de la herramienta CLI de AWS, utilizaremos las credenciales, es decir, la clave secreta y el ID de acceso, que generamos anteriormente para configurar nuestra herramienta CLI ejecutando:

1
$ aws configure

Obtendremos un aviso para completar nuestra ID de clave de acceso, Clave de acceso secreta y regiones predeterminadas y formatos de salida. Los dos últimos son opcionales, pero necesitaremos la clave de acceso y el secreto que obtuvimos del panel de la consola de AWS.

También puede configurar diferentes credenciales para diferentes usuarios en AWS. Puede encontrar más sobre eso y otros detalles aquí.

Configuración del proyecto

Para este proyecto de demostración, construiremos una aplicación Python y es una buena práctica trabajar dentro de un entorno virtual para mantener el entorno de nuestro proyecto abstraído del entorno Python del sistema. Para ello, utilizaremos la herramienta Virtualenv para crear un entorno virtual en el que trabajaremos.

En caso de que la herramienta Virtualenv aún no esté instalada, podemos instalarla simplemente ejecutando:

1
$ pip install virtualenv

Se puede encontrar más información sobre la herramienta Virtualenv aquí.

Con Virtualenv instalado, diríjase a nuestro directorio de trabajo y cree un entorno ejecutando el siguiente comando:

1
$ virtualenv --python=python3 venv-chalice

Activaremos nuestro entorno ejecutando:

1
$ source venv-chalice/bin/activate

Nuestro entorno ahora está configurado, y ahora podemos instalar Chalice y verificar la instalación ejecutando los siguientes comandos:

1
2
$ pip install chalice
$ chalice --help

El segundo comando aquí simplemente se usa para verificar la instalación de Chalice.

Implementación

Ahora tenemos una cuenta de AWS, la herramienta AWS CLI instalada, la configuración del entorno y Chalice instalado. Ahora podemos usar Chalice para crear nuestra API RESTful simple de la siguiente manera:

1
$ chalice new-project demoapp

Este comando crea un proyecto Chalice simple dentro de una carpeta que tiene la siguiente estructura:

1
2
3
4
$ tree demoapp
demoapp
├── app.py
└── requirements.txt

Cualquier otro requisito que requiera nuestra aplicación Chalice para ejecutarse mientras se implementa en AWS Lambda irá al archivo requirements.txt dentro de la carpeta demoapp, y nuestra nueva funcionalidad residirá principalmente en el archivo app.py. Podemos crear otros archivos e importarlos al archivo app.py, que es nuestro archivo de proyecto principal.

Para nuestra API simple, crearemos una API que devuelva una lista de los repositorios públicos de GitHub de un usuario, los idiomas utilizados en cada uno y la cantidad de estrellas que tiene el repositorio. Esta información está disponible públicamente en la API de GitHub, por lo que no necesitaremos credenciales para interactuar con la API. Crearemos una función que reciba un nombre de usuario y devuelva los detalles que necesitamos. Si el nombre de usuario proporcionado no existe, recibiremos una carga útil de respuesta vacía.

Vamos a crear la función github_repos que será responsable de la interacción de la API de GitHub:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests

def github_repos(username):
    # Final list to contain our repository objects
    formatted_repos = []

    if username:
        # Format the url by insterting the passed username
        url = "https://api.github.com/users/{}/repos".format(username)

        r = requests.get(url)

        # Get the JSON containing the list of repositories
        list_of_repos = r.json()

        for repo in list_of_repos:
            repo_object = {
              "name": repo["name"],
              "stars": repo["watchers"],
              "language": repo["language"],
            }

            formatted_repos.append(repo_object)

    return formatted_repos

La función github_repos recibe un nombre de usuario y lo conecta a la URL de la API de GitHub antes de realizar la solicitud. La respuesta recibida tiene mucha información que no necesitamos por ahora, así que extraemos los detalles de un repositorio que necesitamos, creamos un nuevo objeto y lo agregamos a la lista de formatted_repos que enviaremos de regreso al usuario a través de la aplicación Chalice.

Primero ejecutemos algunas pruebas locales para nuestra función y este es el resultado:

local testing output

La función ahora está lista para integrarse en nuestra aplicación Chalice en el archivo app.py, y esta es la versión final de nuestra aplicación:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import requests
from chalice import Chalice

def github_repos(username):
    # Function implementation above

app = Chalice(app_name='demoapp')

@app.route('/')
def index():
    return {'hello': 'world'}

# Create our new route to handle github repos functionality
@app.route('/user/{username}')
def github(username):
    return {"repos": github_repos(username)}

Nuestra aplicación ahora está lista para ser consumida por los usuarios, ahora implementémosla en AWS Lambda.

Desplegando nuestra aplicación

Implementar una aplicación Chalice en AWS Lambda es tan simple como ejecutar el siguiente comando en nuestro directorio de trabajo:

1
$ chalice deploy

Chalice se encargará del proceso de implementación por nosotros y devolverá un enlace con el que podemos interactuar con la API RESTful que acabamos de crear:

chalice deploy output

Para probar nuestra API, podemos usar Cartero, un navegador web o cualquier otra herramienta de interacción API para realizar solicitudes al extremo /user/<github-username>. en la "URL API REST" de la captura de pantalla anterior. Pasé mi nombre de usuario de GitHub y este fue el resultado:

postman response

Si hacemos algún cambio en nuestro código, simplemente ejecutamos el comando chalice deployment nuevamente y Chalice volverá a implementar nuestra aplicación con los cambios que acabamos de hacer.

Cuando nos dirigimos a la consola de AWS y hacemos clic en la sección "Funciones" en la barra lateral plegable del lado izquierdo, podemos ver la función de Lambda que actualmente ejecuta nuestra aplicación:

lambda on aws console

Cuando hacemos clic en nuestra función, obtenemos más detalles sobre ella, como la configuración actual, las variables de entorno establecidas para nuestra aplicación, los roles de ejecución y la configuración de la memoria.

AWS también nos brinda opciones de monitoreo, como registros de eventos y métricas a través de CloudWatch, que es un servicio de monitoreo y administración ofrecido por AWS.

Esta es la vista del panel de control de nuestra aplicación:

cloudwatch monitoring

Obtenemos estadísticas sobre la cantidad de invocaciones de los usuarios, la duración de las solicitudes atendidas por nuestra API, las tasas de éxito y error, entre otras cosas.

Incluso obtenemos una vista de las solicitudes individuales en el mismo tablero, aunque esto no se ve en la captura de pantalla anterior. Hay tanto que AWS hace por nosotros desde el primer momento, lo que hace que nuestra experiencia de implementación sea corta y directa. No tenemos que preocuparnos por mantener nuestro propio servidor o implementar nuestros propios métodos de monitoreo y registro, ya que AWS nos tiene cubiertos para esto.

Esta es la experiencia sin servidor.

Resumen

En este artículo, creamos una API de Python sin servidor utilizando el micromarco Chalice y la implementamos en AWS Lambda. La CLI de AWS, junto con las herramientas de la CLI de Chalice, nos ayudó a iniciar nuestro proyecto rápidamente y lo implementamos en AWS Lambda con un solo comando.

La nuestra es una aplicación sin servidor, ya que no tuvimos que encargarnos de ninguna provisión o mantenimiento del servidor de nuestra parte. Simplemente escribimos el código y dejamos que AWS maneje el resto por nosotros, incluida la implementación, el escalado y el monitoreo de nuestra aplicación. El tiempo necesario para que nuestra aplicación esté disponible ha disminuido significativamente, aunque todavía dependemos de AWS para otros aspectos, como el monitoreo de nuestra aplicación.

El código fuente de este proyecto está disponible aquí en GitHub. mo).