Blog

Despertar bases de dades sense connexions mortes

Les apps publicades a Mythex, i les seves bases de dades, s'adormen quan ningú les fa servir. Quan una app es despertava, podia mantenir la primera petició entre 10 i 12 segons, perquè intentava reutilitzar connexions a la base de dades que havien mort mentre tot dormia. Ara donem a les apps Spring Boot una configuració de base de dades segura per a la son, i indiquem a l'agent que construeixi les apps de qualsevol stack de la mateixa manera. A la plataforma d'allotjament, la primera petició després d'un despertar va passar de 12,7 segons a 2,3 segons.

Per què s'adormen les apps i les bases de dades

Una app publicada de Mythex s'executa en una màquina que es suspèn després de pocs minuts inactiva, i la seva base de dades és un Postgres sense servidor que s'adorm després de cinc minuts inactiva i es desperta amb la següent consulta. Això és el que manté barata una app tranquil·la: pagues pel que la base de dades realment ha fet servir, i una app adormida no gasta res en còmput. Vam escriure sobre la part de facturació a facturar les bases de dades pel que fan servir de veritat.

El problema és que les dues s'adormen per separat, i no es posen d'acord sobre què és una connexió.

El símptoma: una primera visita lenta

La majoria d'aplicacions de servidor mantenen un pool de connexions: un grup de connexions a la base de dades obertes i preparades, perquè cada petició no hagi de pagar el cost d'obrir-ne una de nova. És el disseny correcte per a una app que sempre està activa.

Això és el que passa amb la son:

  1. L'app està en marxa, amb unes quantes connexions inactives al pool.
  2. Ningú no la visita. La màquina de l'app se suspèn (congelada, amb el pool intacte).
  3. La base de dades s'adorm i tanca el seu extrem de totes les connexions.
  4. Arriba un visitant. L'app es desperta exactament com estava, encara amb connexions que la base de dades ja no coneix.
  5. El pool dona una d'aquelles connexions. Ha de descobrir que està morta (provant-la i esperant) abans de descartar-la.

En una app Spring Boot, validar aquelles connexions mortes bloquejava la primera petició durant uns 10 segons abans que fallés amb «Connection is not available». Per al visitant, el lloc simplement es quedava penjat i després potser mostrava un error.

Per què les apps Spring ho tenien pitjor

Spring Boot és un framework Java popular, i fa servir per defecte un pool de connexions anomenat HikariCP. Spring pot configurar aquest pool des de paràmetres, inclòs quantes connexions inactives s'han de mantenir.

Però Mythex dona a cada app la seva base de dades com una sola variable DATABASE_URL amb la forma postgresql://usuari:contrasenya@host/db. Spring no pot llegir directament aquest format. Així que les apps Spring construïdes a Mythex creaven el seu propi pool al codi, analitzant aquella URL, i un pool construït a mà ignora tots els paràmetres spring.datasource.* de Spring. Fins i tot si algú sabia la configuració correcta del pool, no hi havia cap lloc on tingués efecte.

La solució, part 1: paràmetres que Spring pot fer servir

Quan un projecte té una base de dades, ara també li donem variables d'entorn que Spring llegeix de manera nativa:

  • SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME i SPRING_DATASOURCE_PASSWORD, convertides des de DATABASE_URL (amb SSL obligatori tret que la URL digui el contrari).
  • Paràmetres del pool que sobreviuen a la son:
ParàmetreValorPer què
Mínim de connexions inactives0No mantenir res obert entre peticions, així no hi ha res que es pugui quedar desfasat
Temps d'inactivitat30 segonsTancar aviat les connexions no usades
Durada màxima2 minutsRetirar cada connexió abans que pugui envellir
Temps d'espera de connexió5 segonsNo penjar una petició durant molta estona si la base de dades triga a respondre

Sense connexions inactives mantingudes, una app que es desperta obre una connexió nova en lloc d'anar-se'n per entre connexions mortes.

Amb aquestes variables presents, Spring configura el pool ell mateix, i els paràmetres s'apliquen. Qualsevol cosa que el projecte hagi definit ell mateix sempre preval; només omplim el que falta. Les apps que no són Spring ignoren aquestes variables.

El detall que gairebé ho deixava sense efecte

Spring mapeja les variables d'entorn als seus paràmetres amb una regla fàcil d'equivocar. El paràmetre minimum-idle s'ha d'escriure com SPRING_DATASOURCE_HIKARI_MINIMUMIDLE: sense guionets, paraules juntes. Escriure-ho com SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, que sembla més natural, es mapeja a un paràmetre diferent i inexistent (minimum.idle) i s'ignora en silenci.

És el tipus d'error que passa totes les revisions i no fa res en producció. Per això hi ha una prova que comprova tant que els valors estan definits com que cap variable fa servir la forma separada per guions baixos.

La solució, part 2: totes les altres tecnologies

Spring no és l'únic framework amb un pool, i no podem preconfigurar cada biblioteca de cada llenguatge. Així que l'agent de Mythex, la IA que escriu la teva app, ara té una instrucció permanent per a qualsevol stack: les apps publicades i les seves bases de dades s'adormen quan estan inactives, així que una connexió oberta pot estar morta a la següent petició. Ha de:

  • no mantenir connexions inactives obertes a la base de dades, o comprovar-les abans d'usar-les,
  • tornar a intentar una vegada en cas d'error de connexió, i
  • fer servir la configuració de base de dades que la plataforma proporciona a l'entorn, en lloc de construir el seu propi pool analitzant DATABASE_URL.

Aquest últim punt tanca el cercle amb la part 1: una app construïda amb la configuració que es proporciona recull automàticament la configuració segura per a la son.

El resultat

Mesurat a la plataforma d'allotjament on executem les apps publicades, la primera petició després d'un despertar va passar de 12,7 segons a 2,3 segons.

Què ens hem endut

  • Cada capa que s'adorm ha de posar-se d'acord sobre què sobreviu. Una app congelada i una base de dades adormida van fer cadascuna una elecció raonable. Juntes, l'app es despertava amb un estat que ja no era cert.
  • Els valors per defecte pensats per a servidors sempre actius no encaixen amb apps que es redueixen a zero. Mantenir connexions calentes és una bona idea fins que tot el que les envolta es refreda.
  • Dona als frameworks les seves dades en el seu propi format. Una sola URL era simple per a nosaltres, però obligava cada app Spring a fabricar a mà un pool que ignorava la seva pròpia configuració.
  • Prova que un paràmetre està escrit com el framework el llegeix. Un valor correcte amb un nom equivocat no fa res, en silenci.

Si ets nou en com funcionen les bases de dades a Mythex, consulta els documents sobre la base de dades i la nostra explicació de què és Postgres.

Mythex · Pricing · Crea qualsevol cosa amb IA · Plantilles de llocs web i aplicacions · Mythex comparat · Glossari de creació d’aplicacions amb IA · Eines gratuïtes per crear aplicacions amb IA · English

English አማርኛ العربية Български বাংলা Bosanski Čeština Dansk Deutsch Ελληνικά Español 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 简体中文 繁體中文(香港) 繁體中文(台灣)