Blog de Amazon Web Services (AWS)

Consulta tu base de datos de AWS desde una aplicación serverless

Por Deana Holmer, Ingeniera Senior de Bases de Datos en AWS

Los clientes de bases de datos de AWS quieren disminuir costos, escalar sin problemas y contar con alta disponibilidad sin necesidad de aproviosionar instancias de Amazon Elastic Compute Cloud (Amazon EC2) en su nube privada virtual (VPC) para utilizarlos como clientes de bases de datos. Una aplicación que se ejecuta sin aprovisionar ni administrar una instancia de EC2 se conoce como serverless (aplicación sin servidor).

En esta publicacion de blog, muestro cómo consultar una base de datos de AWS desde una URL, incluso si la base de datos no es de acceso público. Este metodo funciona de igual manera, aun si se ejecuta en una base de datos de Amazon Aurora Serverless para realizar una consulta serverless a serverless. Proporciono una selección de scripts de Python que funcionan para Amazon Neptune, Amazon Relational Database Service (Amazon RDS) para MySQL o Amazon RDS para PostgreSQL, respectivamente. También te guiaré en la configuración y creación de los dos siguientes componentes:

Proporciono una plantilla de AWS CloudFormation que facilita la creación de estos componentes. Además, incluyo importantes secciones de Sugerencias y Solución de problemas específicos para consultar bases de datos en una VPC de Amazon que no son estrictamente del tipo no relacionales (NoSQL – key-value).

Los ejemplos de código de Python aplican prácticas recomendadas que se pueden adaptar fácilmente a otros motores de base de datos. Para Neptune, el ejemplo de SPARQL se puede adaptar para-Gremlin.

Puede descargar el código Python y la plantilla de AWS CloudFormation del repositorio de GitHub awslabs/rds-support-tools.

Esta publicación está dirigida a usuarios de bases de datos de AWS que no tienen experiencia con AWS Lambda, Amazon API Gateway o AWS CloudFormation, y que tienen una experiencia limitada con Python. El tiempo para completar los pasos es aproximadamente 30 minutos.

Antes de empezar

 Para saber si una aplicación serverless es adecuada para usted, revise los límites de AWS Lambda y los límites de API Gateway. En particular, tenga en cuenta los límites de tiempo de ejecución que se aplican a sus consultas. Si API Gateway invoca la función Lambda de forma síncrona, se aplica el límite de tiempo de ejecución de API Gateway; si de forma asíncrona, se aplica el límite de tiempo de ejecución de Lambda. Si elige un método de invocación alternativo, se seguirá aplicando el límite de tiempo de ejecución de Lambda. En este ejemplo, invocamos la función Lambda de forma síncrona.

Pre-requisitos

  • Haber aprovisionado una instancia de base de datos de AWS en una VPC, preferiblemente de Neptune, RDS para MySQL o RDS para PostgreSQL
  • Para fines de configuración, ha aprovisionado un cliente temporal de Amazon EC2, preferiblemente Amazon Linux, en la misma región de VPC y AWS que la base de datos.
  • Conocer el ID de la subnet del cliente de EC2 y el ID del grupo de seguridad.
  • El ID del grupo de securidad del cliente (no el CIDR) tiene que estar permitido como origen en la regla de entrada del grupo de seguridad de la base de datos. El rango de puertos incluye el puerto de base de datos.
  • El software cliente de base de datos preferido se ha instalado en el cliente de EC2 y se ha establecido conectividad desde este cliente hacia la base de datos. El usuario de la base de datos tiene permisos para crear objetos, insertar y consultar desde esta base de datos.
  • Tener instalado Python 3.6 en el host cliente. Para obtener ayuda sobre la instalación de Python 3.x en un servidor Amazon Linux mediante virtualenv, consulte uno de estos artículos del Centro de conocimiento de AWS: Instrucciones para Amazon 1 Linux o Instrucciones para Amazon 2 Linux.
  • Su usuario de AWS tiene permisos para crear y administrar roles de IAM, Lambda, API Gateway y stacks de AWS CloudFormation, así como tambien para ver los las bitácoras de eventos (logs) de Amazon CloudWatch.
  • Tienes acceso completo a la consola. También has configurado la CLI de AWS en el de su cliente de EC2 y puede ejecutar el siguiente comando sin ningún error de permiso:  aws s3 ls
  • Si no has usado GitHub antes, consulta estas instrucciones para descargar las herramientas awslabs/rds-support.

 

Pasos

 En las siguientes secciones se describe cómo configurar y probar este ejemplo.

  1. Configure la solución
  2. Cargue los datos de prueba
  3. Pruebe el código Python proporcionado desde la línea de comandos en el host de su cliente EC2
  4. Comprima su código fuente Python junto con los paquetes de Python
  5. Cree la función Lambda y la API REST de API Gateway
  6. Consulte la base de datos desde la URL
  7. Próximos pasos
  8. Sugerencias y solución de problemas
  9. Resumen y pasos finales

Paso 1: Configure la solución

  1. En el host de tu cliente EC2, cree el directorio del proyecto para su base de datos; por ejemplo:

mkdir ~/svls
cd ~/svls

  1. Descargue los scripts y la plantilla JSON de AWS CloudFormation del repositorio de GitHub en el de su cliente EC2.
  2. Renombre el script de Python con el motor de base de datos a serverless-query.py. Mantenga el nombre de la plantilla de AWS CloudFormation: serverless-query-cfn.json.
  3. Instale dos2unix y ejecute todos los archivos a través de él.

sudo yum install -y
dos2unixdos2unix *

  1. Compruebe que su entorno Python 3.6 está activado.

which python
~/venv/python36/bin/python

  1. Desde el entorno virtualenv de Python 3.6, utilize pip3 install para instalar el módulo de tu cliente de base de datos que se importa en el ejemplo de código.
Base de datos Modulo a instalar usando pip3
MySQL pip3 install pymysql
PostgreSQL pip3 install psycopg2-binary
Neptune/SPARQL pip3 install SparqlWrapper
  1. Defina los permisos necesarios:

chmod a+r ~/svls
chmod 744 serverless-query.py
chmod 444 serverless-query-cfn.json

  1. Localice los paquetes que instaló con pip3 y asegúrese de que tienen permisos de lectura globales. Si está usando virtualenv, deberían estar en uno de los siguientes directorios:
ls $VIRTUAL_ENV/lib64/python3.6/site-packages
sudo chmod a+r -R $VIRTUAL_ENV/lib64/python3.6/site-packages

#or

ls $VIRTUAL_ENV/lib/python3.6/site-packages
sudo chmod a+r -R $VIRTUAL_ENV/lib/python3.6/site-packages

Paso 2: Cargue los datos de prueba

Utilice el script de inserción proporcionado para el motor de base de datos para cargar los datos de ejemplo en la base de datos.

Paso 3: Pruebe el código Python proporcionado desde la línea de comandos en el de su cliente EC2

  1. Establezca variables de entorno para una prueba de línea de comandos:

MySQL y PostgreSQL:

export ENDPOINT=’your-database-endpoint’
export PORT=’your-database-port’
export DBUSER=’your-database-user’
export DBPASSWORD=’your-database-user-password’
export DATABASE=’your-database-name’

Neptune:

export ENDPOINT='your-database-endpoint'
export PORT='your-database-port'
export DBUSER='None'           
export DBPASSWORD='None'
export DATABASE='None'
  1. Ejecute el script de Python desde la línea de comandos:

./serverless-query.py 

Resultados esperados con Neptune/SPARQL:

['amzn://data/hello1 , amzn://data/world1', 'amzn://data/hello2 , amzn://data/world2'] 

Resultados esperados con MySQL y PostgreSQL:

[('hello1', 'world1'), ('hello2', 'world2')]  

  1. Puede comentar esta declaración de print. Si lo deja, los resultados de la consulta se imprimirán en la bitácora de eventos de CloudWatch (logs):

# print(results_list) 

 Paso 4: Comprima su código fuente Python junto con los paquetes de Python

  1. Comprima el script junto con el paquete Python del cliente de base de datos que instaló con pip3. Para obtener más información, consulte Creación de un paquete de implementación. Vaya al directorio de paquetes donde se instalaron los paquetes de Python y comprima el contenido del directorio (no el directorio en sí). Coloque el archivo zip en la carpeta de su proyecto. Para incluir todos los archivos ocultos, utilice la opción zip -r9. Si uso virtualenv, sus paquetes cliente se encuentran en uno de los siguientes directorios:
cd $VIRTUAL_ENV/lib64/python3.6/site-packages
zip -r9 ~/svls/serverless-query.zip *

# or

cd $VIRTUAL_ENV/lib/python3.6/site-packages
zip -r9 ~/svls/serverless-query.zip *
  1. En el directorio de su proyecto, añada el script serverless-query.py al archivo zip:

cd ~/svlszip -g serverless-query.
zip serverless-query.py

Paso 5: Cree la función Lambda y la API REST de API Gateway

  1. Desde el cliente EC2, cree un repositorio (bucket) de Amazon S3 si no tiene uno.

 aws s3 mb s3://your-s3-bucket-name

  1. Cargue el archivo zip en su repositorio (bucket) de S3:

aws s3 cp serverless-query.zip s3://your-s3-bucket-name

  1. Cree el stack de AWS CloudFormation mediante la CLI de AWS.
aws cloudformation create-stack \
--stack-name serverless-query-cfn \
--template-body file://serverless-query-cfn.json \
--region your-database-region \
--capabilities CAPABILITY_NAMED_IAM \
--parameters '[
   {"ParameterKey":"PEndpoint","ParameterValue":"your-database-endpoint"},
   {"ParameterKey":"PPort","ParameterValue":"your-database-port"},
   {"ParameterKey":"PDatabase","ParameterValue":"your-database-name"},
   {"ParameterKey":"PDbUser","ParameterValue":"your-db-user-name"},
   {"ParameterKey":"PDbPassword","ParameterValue":"your-db-user-password"},
   {"ParameterKey":"PS3Bucket","ParameterValue":"your-S3-bucket-name"},
   {"ParameterKey":"PSubnetIds","ParameterValue":"your-EC2-client-SubnetId"},
   {"ParameterKey":"PSecurityGroupIds","ParameterValue":"your-EC2-client-SecurityGroupId"}
 ]'

Los usuarios de Neptune deben establecer estas variables en “None”:

   {"ParameterKey":"PDatabase","ParameterValue":"None"},
   {"ParameterKey":"PDbUser","ParameterValue":"None"},
   {"ParameterKey":"PDbPassword","ParameterValue":"None"},
  1. En el panel de control de la consola de AWS CloudFormation, consulte la pestaña Events y busque el stack serverless-query-cfn para ver el progreso. Si el estado del stack es ROLLBACK_COMPLETE, revise el motivo del error en la pestaña Events. Para obtener más información, consulte solución de problemas y sugerencias para realizar cambios más adelante en esta publicación.

  1. Cuando el estado de la pila es CREATE_COMPLETE, pruebe la función Lambda desde la línea de comandos:
rm -f invoke-lambda.out
aws lambda invoke \
--function-name ServerlessQuery \
--region your-database-region \
--log-type Tail invoke-lambda.out
echo **Return Object**
cat invoke-lambda.out

Para solucionar cualquier problema, consulte la bicácora de eventos de CloudWatch y las secciones solución de problemas y sugerencias para realizar cambios más adelante en esta publicación.

Para revisar la bicácora de eventos de CloudWatch:

  1. Abra la consola de CloudWatch.
  2. En el panel de navegación de la izquierda, seleccione Logs.
  3. Elija /aws/Lambda/ServerlessQuery.
  4. Elija el registro de la bitácora de eventos (Logs) que tenga la última hora del último evento.

A menos que haya comentado la instrucción print (results_list) del script Python, también verá el resultado de la consulta en el flujo de la bitácora de eventos (Logs).

Paso 6: Consulte la base de datos desde la URL

Tienes dos opciones para consultar su base de datos:

Opción 1: Utilizando curl hacia la URL desde la línea de comandos:

Obtenga el ID del API:

aws apigateway get-rest-apis

Después:

curl https://api-id.execute-api.your-database-region.amazonaws.com/beta/query1

Opción 2: Pegando la URL en un navegador:

Vaya al panel de control de API Gateway. Corte y pegue la «invoke URL » de su beta Stage Editor en un navegador y añada su nombre de recurso /query1 al final de la misma.

Para solucionar cualquier problema, consulte la bitácora de eventos de CloudWatch y las secciones Solución de problemas y sugerencias para realizar cambios.

Vea los resultados de la consulta desde el navegador:

Paso 7: Siguientes pasos

Después de configurar y probar su aplicación serverless, aquí encontrará algunas prácticas recomendadas y tareas de administración que puede realizar para ayudar en la optimización de la solución.

  • Proteja la contraseña de su base de datos y otras variables de conexión cifrando las variables de entorno de Lambda con claves de AWS KMS.
  • Aumente la disponibilidad añadiendo una segunda sub-red a la configuración de la VPC de la función Lambda.
  • Si planea llamar a tu API desde un sitio externo, como un sitio web estático de S3, debe habilitar CORS (uso compartido de recursos entre orígenes) para su recurso de API Gateway. Tenga en cuenta que la respuesta de integración está deshabilitada para la integración de proxy, que hemos utilizado aquí. Esto significa que, al configurar los encabezados de respuesta para CORS, debe confiar en que el back-end devuelva los encabezados Access-Control-Allow-Origin.
  • Para facilitar la administración de sus plantillas de AWS CloudFormation para aplicaciones serverless, pruebe el modelo de aplicación sin servidor de AWS (AWS SAM).

Paso 8: Sugerencias y solución de problemas

A medida que complete los pasos de este ejemplo, utilice la siguiente guía para solucionar cualquier problema que pueda surgir.

Consejos para ejecutar consultas de larga duración

En el ejemplo se utiliza la configuración de tiempo limite de ejecución (timeout) predeterminada para ejecutar una consulta breve. Para ejecutar consultas más largas, puede realizar cualquiera de las siguientes acciones:

  • Aumente los parámetros de timeout para ambos API Gateway y Lambda hasta sus respectivos límites de tiempo de ejecución. Para la invocación síncrona, es posible que deba establecer el timeout de Lambda ligeramente inferior al timeout de API Gateway para permitir que la API REST finalice de forma limpia.
  • Invoque a Lambda de forma asíncrona, para que solo se aplique el límite de Lambda.
  • Cree la función Lambda y, a continuación, elija un método de invocación alternativo. El límite de tiempo de ejecución de Lambda aún aplica.
  • Mueva el trabajo al área de back-end. Por ejemplo, utilice una vista materializada o un trabajo por lotes personalizado para procesar la consulta local y automáticamente, de modo que el resultado de resumen se pueda consultar desde una función de Lambda dentro del límite de tiempo de ejecución.
  • Asegúrese de que los datos estén indexados correctamente y que la consulta esté optimizada. Utilice particiones y filtros para consultar el conjunto de datos más pequeño posible. Almacene en caché los resultados si es adecuado para su aplicación.
  • Limite el resultado de las consultas mediante la cláusula LIMIT o una equivalente.

 

Consejos para ejecutar el código Python

Las muestras de código de Python utilizan prácticas recomendadas cuando se trabaja con Lambda, API Gateway, y en specifico las dos bases de datos relacionales y la base de datos de grafos de los ejemplos: MySQL, PostgreSQL y Neptune (SPARQL), respectivamente. Las prácticas recomendadas son las siguientes.

  • Inicialice variables y realice otras operaciones de arranque desde fuera de la función de controlador de Lambda. Esto permite que el bootstrapping se ejecute una sola vez, desde el entorno de ejecución de Lambda (anteriormente conocido como “container”). Siempre que el entorno de ejecución esté activo, solo se ejecutaran las operaciones dentro de la función de controlador.
  • Una buena práctica habitual en Lambda, es abrir la conexión de base de datos en el entorno de ejecución de Lambda para que se pueda reutilizar con cada llamada al controlador. Si la conexión a la base de datos se interrumpe en algún momento, se vuelve a conectar desde el controlador. El uso de una variable de conexión global dentro del controlador garantiza que cualquier conexión nueva permanezca abierta para llamadas posteriores. Pero en el caso de MySQL y PostgreSQL existe el riesgo de que se produzcan fugas de sesión a través de la conexión abierta que pueden provocar problemas de bloqueo. Por lo tanto, aunque nuestro ejemplo simple es una consulta de solo lectura, abrimos y cerramos la conexión en cada llamada de controlador para evitar este problema potencial. Usuarios de Neptune: Esto no se aplica al código de ejemplo de SPARQL porque no establece una conexión de base de datos persistente.
  • API Gateway requiere el objeto sea retornado dentro del controlador. Úsalo en lugar de sys.exit () para salir con gracia. De lo contrario, es posible que veas errores 502 que informan de una «Respuesta proxy Lambda incorrectamente formada».

Sugerencias sobre latencias

Si eres nuevo en el uso de AWS Lambda, es posible que tenga preguntas sobre las latencias relacionadas con Lambda. Estas latencias se explican aquí.

  • La primera llamada de Lambda puede tardar más de lo esperado porque incluye pasos de arranque (inicio en frío) que no se realizan en llamadas posteriores (inicio en caliente).
  • Tras un período de inactividad, los entornos de ejecución de Lambda Esta acción puede provocar una penalización en el rendimiento del arranque en frío la próxima vez que se llame a la función Lambda. Esta penalización de rendimiento se manifiesta como un pico de latencia.
  • A continuación se muestra un ejemplo de tiempos de inicio en caliente frente a tiempo transcurrido de arranque en frío para la misma consulta:
arranque en caliente arranque en frio
time ./invoke-lambda.cli
real    0m0.389s
time ./invoke-lambda.cli}
real    0m9.428s

Consejos para hacer cambios

Es mejor evitar eliminar y volver a crear componentes de AWS individuales que tengan interdependencias. Los siguientes consejos le ayudarán a realizar los cambios que necesite.

  • Para cambiar los parámetros del stack de AWS CloudFormation, actualice el stack. Consulte el script de ejemplo update-stack.cli en GitHub.
  • Para cambiar el código de Python, vuelva a comprimir y actualice la función Lambda. Consulte el script de ejemplo update-lambda.cli en GitHub.
  • También puede eliminar toda la pila de AWS CloudFormation y empezar de nuevo. Pero tenga en cuenta que la pila que se utiliza en este ejemplo contiene una configuración de VPC que crea una interfaz de red elástica. La interfaz de red tarda un tiempo en limpiarse, por lo que la eliminación puede tardar un poco.

Sugerencias para usar y escalar una función Lambda habilitada para VPC

Las funciones Lambda habilitadas para VPC plantean desafíos especiales, especialmente en lo que respecta al escalamiento. Los siguientes consejos le guiarán para afrontar estos desafíos.

  • Las interfaces de red creadas para funciones Lambda habilitadas para VPC se les asigna una dirección IP privada en la sub-red. Por lo tanto, la función Lambda no tiene acceso a Internet aunque la propia sub-red sea pública. Si la función Lambda requiere acceso a Internet, cree una ruta a una puerta de enlace de traducción de direcciones de red (NAT), en lugar de a una puerta de enlace de Internet, en la tabla de rutas a la que está asociada la sub-red.
  • Asegúrese de que las sub-redes tengan suficientes direcciones IP para gestionar la concurrencia esperada en la función Lambda.
  • Puesto que hay límites en la velocidad a la que puede solicitar las interfaces de red, asegúrese de que la función Lambda tenga suficiente capacidad de interfaz de red. Monitoree el uso de memoria de la función Lambda y reduzca su asignación de memoria no utilizada, ya que esto aumenta el uso compartido de la interfaz de red.
  • Si su base de datos es de acceso público, probablemente no necesite poner su función Lambda en una VPC.

Más consejos

Consulte los siguientes recursos para obtener orientación adicional a medida que sigue los pasos de este ejemplo.

Solución de problemas

Estos son algunos problemas comunes que pueden surgir, y algunas soluciones sugeridas para esos problemas.

Problema: El código de Python se ejecuta desde la línea de comandos, pero se bloquea o se agota el tiempo de espera cuando se hace la llamada a la función Lambda o la API REST de API Gateway.

  • Asegúrese de que la base de datos, el host del cliente EC2 y el stack de AWS CloudFormation se creen en la misma VPC y en la misma región de AWS.
  • Compruebe el groupo de seguridad de base de datos. Asegúrese de que el ID del grupo de seguridad del del cliente EC2, no su CIDR, esté permitido como origen en las reglas de entrada.
  • Es posible que la función Lambda esté fallando y se esté reintentando. Consulte bitácora de CloudWatch para ver errores y métricas de CloudWatch para problemas de recursos.
  • Si está probando una consulta que no sea el ejemplo sencillo que se proporcionó, consulte Sugerencias para ejecutar consultas de larga duración. También pruebe la consulta sencilla que se proporcionó.

Problema: La consulta simple finaliza, pero tarda mucho en ejecutarse.

  • Consulte la sección Consejos sobre latencias e intente llamar la función Lambda dos veces para comparar los arranques en frío y en caliente.

Problema: Aparece el error Unable to import module:

  • Consulte la bitácora de eventos de CloudWatch para obtener información adicional.
  • Compruebe que el archivo de código fuente se llame serverless-query.py, que el archivo zip sea serverless-query.zip y que el nombre del controlador de la plantilla de AWS CloudFormation sea serverless-query.handler.
  • Compruebe que todos los permisos se hayan establecido según las instrucciones.
  • Descomprima serverless-query.zip y compruebe que serverless-query.py se encuentra en el directorio raíz.
  • Vuelva a comprimir los archivos exactamente según las instrucciones.
  • En el comando create-stack, verifique que el nombre del bucket de S3 sea correcto y que tenga el formato nombre-del-bucket (sin prefijo S3://). Compruebe que la última versión de serverless-query.zip está en el bucket. Comprueba los permisos del bucket.
  • Compruebe si hay errores tipográficos en los parámetros del comando create-stack.

Problema: El stack de AWS CloudFormation tarda mucho en eliminarse. El log de AWS CloudFormation muestra un mensaje como:

CloudFormation is waiting for Network Interfaces associated with the Lambda Function to be cleaned up.

  • Este es el comportamiento esperado. Para obtener más información, consulte Consejos para realizar cambios

Problema: Al llamar a la API REST se produce el error {"message":"Missing Authentication Token"}.

  • Añada el nombre del recurso “\ query1” a la URL.

Problema: Llamar a la API REST genera el error “SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data.

  • Pruebe de nuevo desde un navegador que no sea Mozilla Firefox.

Para todos los demás mensajes de error: Consulte bitácora de ventos de CloudWatch para obtener información adicional.

Resumen y pasos finales

Las aplicaciones serverless ofrecen ventajas como alta disponibilidad, flexibilidad y facilidad de administración. Este artículo proporciona un ejemplo de cómo configurar una aplicación serverless y consultar una base de datos de AWS desde una URL, incluso si la base de datos no es de acceso público. Los pasos del ejemplo le guiaron a través de la configuración, las pruebas y la solución de problemas de la solución.

El último paso consiste en eliminar el cliente EC2 si ya no lo necesita. Porque, después de todo, ese era el punto. :)

Este artículo fue traducido del Blog de AWS en Inglés.


Sobre el autor

Deana Holmer es ingeniero senior de bases de datos en el equipo de soporte Premium de Amazon Web Services.

Sobre el traductor

Carlos Robles es Arquitecto de Soluciones especializado en base de datos en AWS. Él Trabaja con clientes de AWS para proporcionar orientación y asistencia técnica en servicios de bases de datos relacionales, ayudándoles a mejorar el valor de sus soluciones cuando utilizan AWS.

Conozca más contenidos sobre base de datos en la página de sesiones bajo demanda.

Acceda >