Blog

Despertar bases de datos sin conexiones muertas

Las apps publicadas en Mythex, y sus bases de datos, entran en reposo cuando nadie las usa. Cuando una app despertaba, podía retener su primera petición entre 10 y 12 segundos, porque intentaba reutilizar conexiones a la base de datos que habían muerto mientras todo dormía. Ahora damos a las apps Spring Boot una configuración de base de datos segura tras el reposo, y le indicamos al agente que construya apps de cualquier stack de la misma forma. En la plataforma de alojamiento, la primera petición tras un despertar pasó de 12,7 segundos a 2,3 segundos.

Por qué duermen las apps y las bases de datos

Una app publicada de Mythex se ejecuta en una máquina que se suspende tras unos minutos inactiva, y su base de datos es un Postgres sin servidor que entra en reposo tras cinco minutos inactiva y despierta con la siguiente consulta. Eso es lo que mantiene barata una app tranquila: pagas por lo que la base de datos realmente usó, y una app en reposo no gasta nada en cómputo. Escribimos sobre el lado de la facturación en cobrar las bases de datos según lo que realmente usan.

La trampa es que ambas duermen por separado, y no están de acuerdo sobre qué es una conexión.

El síntoma: una primera visita lenta

La mayoría de las apps de servidor mantienen un pool de conexiones: un puñado de conexiones abiertas a la base de datos listas para usar, para que cada petición no pague el coste de abrir una nueva. Ese es el diseño correcto para una app que siempre está encendida.

Esto es lo que pasa con el reposo:

  1. La app está en ejecución, con algunas conexiones inactivas en su pool.
  2. Nadie la visita. La máquina de la app se suspende, congelada, con su pool intacto.
  3. La base de datos entra en reposo y cierra su extremo de cada conexión.
  4. Llega un visitante. La app despierta exactamente como estaba, todavía con conexiones que la base de datos ya no conoce.
  5. El pool entrega una de esas conexiones. Tiene que averiguar que está muerta (probándola y esperando) antes de descartarla.

En una app Spring Boot, validar esas conexiones muertas bloqueaba la primera petición unos 10 segundos antes de fallar con «Connection is not available». Para el visitante, el sitio simplemente se colgaba y luego quizá mostraba un error.

Por qué las apps Spring fueron las más afectadas

Spring Boot es un framework Java popular, y usa de forma predeterminada un pool de conexiones llamado HikariCP. Spring puede configurar ese pool desde ajustes, incluido cuántas conexiones inactivas mantener.

Pero Mythex entrega a cada app su base de datos como una única DATABASE_URL con la forma postgresql://user:pass@host/db. Spring no puede leer ese formato directamente. Así que las apps Spring construidas en Mythex creaban su propio pool en código, analizando esa URL, y un pool construido a mano ignora todos los ajustes spring.datasource.* de Spring. Incluso si alguien conocía los ajustes correctos del pool, no había ningún lugar donde tuvieran efecto.

La solución, parte 1: ajustes que Spring puede usar

Cuando un proyecto tiene una base de datos, ahora también recibe variables de entorno que Spring lee de forma nativa:

  • SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME y SPRING_DATASOURCE_PASSWORD, convertidas desde DATABASE_URL (con SSL obligatorio salvo que la URL indique otra cosa).
  • Ajustes del pool que sobreviven al reposo:
AjusteValorPor qué
Conexiones inactivas mínimas0No mantener nada abierto entre peticiones, así que no hay nada que caduque
Tiempo de inactividad30 segundosCerrar pronto las conexiones sin uso
Vida máxima2 minutosRetirar cada conexión antes de que pueda envejecer
Tiempo de espera de conexión5 segundosNo bloquear una petición mucho tiempo si la base de datos tarda en responder

Sin conexiones inactivas retenidas, una app que despierta abre una conexión nueva en lugar de abrirse paso entre conexiones muertas.

Con estas variables presentes, Spring configura el pool por sí mismo y los ajustes se aplican. Lo que el proyecto haya configurado por su cuenta siempre prevalece; nosotros solo rellenamos lo que falta. Las apps que no son Spring ignoran estas variables.

El detalle que casi no hizo nada

Spring asigna las variables de entorno a sus ajustes con una regla fácil de equivocar. El ajuste minimum-idle debe escribirse como SPRING_DATASOURCE_HIKARI_MINIMUMIDLE: sin guiones y con las palabras unidas. Escribirlo como SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, que parece más natural, se asigna a otro ajuste distinto que no existe (minimum.idle) y se ignora en silencio.

Ese es el tipo de error que supera todas las revisiones y no hace nada en producción. Por eso una prueba comprueba tanto que los valores están definidos como que ninguna variable usa la forma con guiones bajos.

La solución, parte 2: todos los demás stacks

Spring no es el único framework con un pool, y no podemos preconfigurar todas las bibliotecas en todos los lenguajes. Así que el agente de Mythex (la IA que escribe tu app) recibe ahora una instrucción permanente para cualquier stack: las apps publicadas y sus bases de datos entran en reposo cuando están inactivas, así que una conexión mantenida abierta puede estar muerta en la siguiente petición. Debe:

  • no mantener conexiones inactivas abiertas a la base de datos, o comprobar cada una antes de usarla,
  • reintentar una vez ante un error de conexión, y
  • usar los ajustes de base de datos que la plataforma proporciona en el entorno, en lugar de construir su propio pool analizando DATABASE_URL.

Ese último punto cierra el círculo con la parte 1: una app construida sobre los ajustes proporcionados recoge la configuración segura frente al reposo automáticamente.

El resultado

Medido en la plataforma de alojamiento donde ejecutamos las apps publicadas, la primera petición tras un despertar pasó de 12,7 segundos a 2,3 segundos.

Lo que aprendimos

  • Cada capa que duerme tiene que estar de acuerdo en lo que sobrevive. Una app congelada y una base de datos en reposo tomaron cada una una decisión razonable. Juntas, la app despertó con un estado que ya no era cierto.
  • Los valores predeterminados pensados para servidores siempre encendidos no encajan con apps que escalan a cero. Mantener las conexiones calientes es una buena idea hasta que todo lo que las rodea se enfría.
  • Entrega a los frameworks sus datos en su propio formato. Una sola URL era simple para nosotros y obligaba a cada app Spring a construir a mano un pool que ignoraba su propia configuración.
  • Prueba que un ajuste se escribe como el framework lo lee. Un valor correcto con el nombre equivocado no hace nada, en silencio.

Si eres nuevo en cómo funcionan las bases de datos en Mythex, consulta la documentación de bases de datos y nuestra explicación sobre qué es Postgres.

Mythex · Pricing · Crea lo que quieras con IA · Plantillas de sitios web y apps · Mythex comparado · Glosario para crear apps con IA · Herramientas gratis para crear apps con IA · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)