Buđenje baza podataka bez mrtvih konekcija
Objavljene aplikacije na Mythexu, zajedno sa svojim bazama podataka, idu na spavanje kada ih niko ne koristi. Kada bi se aplikacija probudila, znala je prvi zahtjev zadržati 10 do 12 sekundi, jer je pokušavala da ponovo upotrijebi konekcije ka bazi koje su umrle dok je sve spavalo. Sada Spring Boot aplikacijama dajemo podešavanja baze koja su sigurna nakon spavanja, a agentu govorimo da aplikacije svakog stacka grade na isti način. Na hosting platformi, prvi zahtjev nakon buđenja smanjio se sa 12,7 na 2,3 sekunde.
Zašto aplikacije i baze spavaju
Objavljena Mythex aplikacija radi na mašini koja se suspenduje nakon nekoliko minuta neaktivnosti, a njena baza je serverless Postgres koji spava nakon pet minuta neaktivnosti i budi se na sljedeći upit. Zbog toga tiha aplikacija ostaje jeftina: plaćate onoliko koliko baza zaista koristi, a aplikacija koja spava ne troši ništa na računanje. O tome s aspekta naplate pisali smo u naplati baza prema onome što zaista koriste.
Ulov je u tome što njih dvije spavaju odvojeno i ne slažu se šta je konekcija.
Simptom: spor prvi posjet
Većina serverskih aplikacija drži connection pool: nekoliko otvorenih konekcija ka bazi koje su spremne, pa svaki zahtjev ne plaća trošak otvaranja nove. To je ispravan dizajn za aplikaciju koja je uvijek aktivna.
Evo šta se dešava sa spavanjem:
- Aplikacija radi, s nekoliko neaktivnih konekcija u poolu.
- Niko je ne posjećuje. Mašina aplikacije se suspenduje, zamrznuta, s netaknutim poolom.
- Baza ide na spavanje i zatvara svoj kraj svake konekcije.
- Stigne posjetilac. Aplikacija se budi tačno onakva kakva je bila, i dalje držeći konekcije za koje baza više ne zna.
- Pool daje jednu od tih konekcija. Mora da sazna da je mrtva, pokušajem i čekanjem, prije nego što je odbaci.
U Spring Boot aplikaciji, provjera tih mrtvih konekcija blokirala je prvi zahtjev oko 10 sekundi prije nego što bi pao s porukom „Connection is not available“. Posjetiocu se sajt jednostavno zamrznuo, pa bi na kraju prikazao grešku.
Zašto su Spring aplikacije najviše stradale
Spring Boot je popularan Java framework, a po defaultu koristi pool konekcija koji se zove HikariCP. Spring može da konfiguriše taj pool iz podešavanja, uključujući koliko neaktivnih konekcija da drži.
Ali Mythex svakoj aplikaciji daje bazu kao jednu varijablu DATABASE_URL u obliku postgresql://user:pass@host/db. Spring ne može direktno čitati taj format. Zato su Spring aplikacije izgrađene na Mythexu sastavljale vlastiti pool u kodu parsirajući taj URL, a pool napravljen ručno ignoriše sva Springova spring.datasource.* podešavanja. Čak i kada bi neko znao ispravna podešavanja poola, nije bilo mjesta gdje bi ona stupila na snagu.
Popravka, dio 1: podešavanja koja Spring može koristiti
Kada projekat ima bazu, sada mu dajemo i varijable okruženja koje Spring čita nativno:
SPRING_DATASOURCE_URL,SPRING_DATASOURCE_USERNAMEiSPRING_DATASOURCE_PASSWORD, pretvorene izDATABASE_URL(uz zahtijevan SSL, osim ako URL kaže drugačije).- Podešavanja poola koja preživljavaju spavanje:
| Podešavanje | Vrijednost | Zašto |
|---|---|---|
| Minimum neaktivnih konekcija | 0 | Ne držati ništa otvoreno između zahtjeva, pa nema šta da zastari |
| Idle timeout | 30 sekundi | Brzo zatvoriti neiskorišćene konekcije |
| Maksimalni životni vijek | 2 minute | Povući svaku konekciju prije nego što ostari |
| Connection timeout | 5 sekundi | Ne držati zahtjev dugo ako baza sporo odgovara |
Kada se ne drže neaktivne konekcije, probuđena aplikacija otvara jednu novu konekciju umjesto da se probija kroz mrtve.
Kada su ove varijable prisutne, Spring sam konfiguriše pool i podešavanja stupaju na snagu. Sve što je projekat sam postavio uvijek pobjeđuje; mi popunjavamo samo ono što nedostaje. Aplikacije koje nisu Spring ignorišu ove varijable.
Detalj koji je skoro sve poništio
Spring mapira varijable okruženja na svoja podešavanja pravilom koje je lako pogrešno napisati. Podešavanje minimum-idle mora se zapisati kao SPRING_DATASOURCE_HIKARI_MINIMUMIDLE: crtice se izostavljaju, riječi se spajaju. Ako se zapiše kao SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, što izgleda prirodnije, mapira se na drugo, nepostojeće podešavanje (minimum.idle) i tiho se ignoriše.
To je vrsta greške koja prođe svaki pregled i ne uradi ništa u produkciji. Zato test provjerava i da su vrijednosti postavljene i da nijedna varijabla ne koristi oblik s donjim crtama.
Popravka, dio 2: svi ostali stackovi
Spring nije jedini framework s poolom, a ne možemo unaprijed konfigurisati svaku biblioteku na svakom jeziku. Zato AI agent koji piše vašu aplikaciju sada dobija stalno uputstvo za svaki stack: objavljene aplikacije i njihove baze spavaju kada su neaktivne, pa konekcija koja je otvorena može biti mrtva pri sljedećem zahtjevu. Agent treba da:
- ne drži otvorene neaktivne konekcije ka bazi, ili provjeri svaku prije upotrebe,
- jednom ponovi zahtjev pri grešci u konekciji, i
- koristi podešavanja baze koja platforma daje u okruženju, umjesto da sam pravi pool parsirajući
DATABASE_URL.
Ta posljednja tačka zatvara krug s dijelom 1: aplikacija izgrađena na obezbijeđenim podešavanjima automatski dobija konfiguraciju sigurnu za spavanje.
Rezultat
Mjereno na hosting platformi na kojoj pokrećemo objavljene aplikacije, prvi zahtjev nakon buđenja smanjio se sa 12,7 sekundi na 2,3 sekunde.
Šta smo iz toga izvukli
- Svaki sloj koji spava mora se složiti šta preživljava. Zamrznuta aplikacija i baza koja spava napravile su svaka razuman izbor. Zajedno, aplikacija se probudila sa stanjem koje više nije bilo istinito.
- Podrazumijevane vrijednosti dizajnirane za servere koji su uvijek aktivni ne odgovaraju aplikacijama koje se skaliraju na nulu. Držati konekcije toplima je dobra ideja dok sve oko njih ne ohladi.
- Dajte frameworku njegove podatke u njegovom formatu. Jedan URL bio je jednostavan za nas, ali je natjerao svaku Spring aplikaciju da ručno pravi pool koji ignoriše vlastitu konfiguraciju.
- Testirajte da je podešavanje napisano onako kako ga framework čita. Ispravna vrijednost pod pogrešnim imenom ne radi ništa, tiho.
Ako ste novi u tome kako baze rade na Mythexu, pogledajte dokumentaciju o bazama i naš vodič o šta je Postgres.