DEV Community

Cover image for Tuning de conexiones en MongoDB con Serverless Lambda
Ignacio Mattos
Ignacio Mattos

Posted on

Tuning de conexiones en MongoDB con Serverless Lambda

Contexto

Luego de una etapa de gestión y mantenimiento manual de una base de datos MongoDB (nosql) instalada on premise, se tomó la decisión de comenzar a usar el servicio cloud Mongo Atlas. Esto se debió a que el mismo ofrece múltiples ventajas -de las cuales “replication” es la más destacable, ofreciendo la posibilidad de implementar la base de datos en un cluster de nodos de forma rápida y eficiente. También ofrece buenas herramientas para monitorear tanto la escalabilidad de la base de datos como los estados del cluster.

Mongo Atlas Monitor

Problema

Al comenzar a utilizar Mongo Atlas, se observó que crecía exageradamente el número de conexiones concurrentes abiertas –alcanzando, por ejemplo, picos de 100 conexiones con un test de carga de solo 5 usuarios simultáneos. Esto derivó en dos escenarios de error:

  • Escenario en el que el backend (AWS Lambda) terminaba requests por timeout debido a problemas de conexión.
  • Caída de la base de datos en caso de haber superado el límite de conexiones de ese momento (500).

Diagnóstico

Tomando como referencia a la documentación de Mongoose y Lambda se encuentra que, al estar acotado el parámetro poolSize de las conexiones a la BD (por defecto 5) y al mismo tiempo no definido un tope para la cantidad de containers (instancias) de Lambda Functions que AWS levanta / crea on-demand, AWS está levantando containers arbitrariamente según el tráfico y requests que recibe el servicio (a través de API Gateway).

Por otra parte, debido a que la API está desplegada en una sola Lambda (donde internamente corre un API Express), todos los requests a diferentes recursos los gestiona un único container. Por ende, este recibe varios requests concurrentes y todos son atendidos por un único pool de conexiones. Dicho de otra manera, cada instancia de Lambda podrá procesar únicamente 5 operaciones concurrentes con acceso a base de datos.

Debido a que AWS no tiene predefinido un tope límite de instancias creadas, estas son creadas a medida que son necesarias para de esta manera “balancear” el tráfico. Por ese motivo, y ya que por cada container Mongoose está creando un pool de 5 conexiones: si AWS levanta 20 containers vivos, levantamos con 100 conexiones en Mongo Atlas, exponiéndolo a la condición de saturación con la que nos encontramos.

Alcanzar el límite de conexiones del cluster puede afectar el rendimiento y la disponibilidad de la base de datos o, en el peor de los casos, generar una caída en el servidor, requiriendo un reinicio manual.

Solución

Ya que el pool de conexiones al cluster es proporcional a la cantidad de containers creados por AWS, se decidió poner un límite al número de containers vivos que pueden existir. Para este caso definimos un máximo de 20 instancias a través de la opción reservedConcurrency en nuestro archivo serverless.yml para configurar el serverless framework.

functions:
   <api_name>:
      reservedConcurrency: 20
      timeout: 20
      memorySize: 1536
Enter fullscreen mode Exit fullscreen mode

Asimismo y tomando en consideración este parámetro buscamos un valor para poolSize que nos permitiera tener el mayor número de conexiones en el pool disponible sin superar el límite del cluster: 20 x 24 = 480 parece un escenario más conservador y, al mismo tiempo, más eficiente en el uso de los recursos. De la siguiente manera configuramos la conexión a la base desde nuestra API Express:

const db = await.mongoose.connect(mongodbUri, {
   poolSize: 24 
});
Enter fullscreen mode Exit fullscreen mode

Otra configuración viable podría ser 30 x 16; léase, 30 instancias máximo de containers Lambdas x 16 conexiones reservadas en pool.

Monitoreo y conclusión

Luego de las medidas tomadas, no se observaron picos en la apertura de conexiones con lo cual se concluye que la solución fue efectiva.

Es igualmente recomendable darle un seguimiento al performance del cluster de la base de datos, observando las estadísticas de conexiones y gestionando alertas para casos en los que dicho número de conexiones se acerque a las 480.

En lo que concierne al API, es a su vez recomendable observar y buscar errores 5xx dentro de API Gateway y configurar alertas en caso de que sean persistentes en un corto período de tiempo (downtime).


Quiero agradecer a @frangeris por su colaboración y aportes en el diagnóstico y la construcción de una solución acorde al escenario en cuestión, así como también en su documentación posterior.

Imagen del encabezado tomada de Nick Van Hook (2020). "Marrying Mongodb Atlas and AWS Lambda."

Top comments (1)

Collapse
 
frangeris profile image
Frangeris Peguero

Un placer 🙇‍♂️