Buđenje baza podataka bez mrtvih konekcija
Objavljene aplikacije na Mythexu, kao i njihove baze, odlaze na spavanje kada ih niko ne koristi. Kada bi se aplikacija probudila, mogla je da drži prvi zahtev 10–12 sekundi, jer je pokušavala da ponovo upotrebi konekcije ka bazi koje su umrle dok je sve spavalo. Sada Spring Boot aplikacijama dajemo podešavanja baze koja su bezbedna i nakon spavanja, a agentu kažemo da grad aplikacije bilo kog steka gradi na isti način. Na hosting platformi, prvi zahtev posle buđenja smanjen je sa 12,7 sekundi na 2,3 sekunde.
Zašto aplikacije i baze spavaju
Objavljena Mythex aplikacija radi na mašini koja se posle nekoliko minuta neaktivnosti suspenduje, a njena baza je serverless Postgres koji spava posle pet minuta neaktivnosti i budi se na sledeći zahtev. To je ono što drži tihu aplikaciju jeftinom: plaćate ono što baza zaista koristi, a uspavana aplikacija ne troši ništa na računanje. O tome kako to funkcioniše sa naplatom pisali smo u tekstu naplata baza podataka po onome što zaista koriste.
Problem je u tome što se njih dve uspavljuju odvojeno i ne slažu se oko toga šta je konekcija.
Simptom: spora prva poseta
Većina serverskih aplikacija održava connection pool: mali broj otvorenih konekcija ka bazi koje čekaju spremne, tako da svaki zahtev ne plaća cenu otvaranja nove. To je pravi dizajn za aplikaciju koja je uvek aktivna.
Evo šta se dešava uz spavanje:
- Aplikacija radi, sa nekoliko neaktivnih konekcija u pool-u.
- Niko ne posećuje. Mašina aplikacije se suspenduje, zamrznuta, sa netaknutim pool-om.
- Baza odlazi na spavanje i zatvara svoj kraj svake konekcije.
- Posetilac stiže. Aplikacija se budi tačno onakva kakva je bila, i dalje drži konekcije koje baza više ne poznaje.
- Pool izdaje jednu od tih konekcija. Mora da sazna da je mrtva, pokušavajući da je upotrebi i čekajući, pre nego što je odbaci.
U Spring Boot aplikaciji, provera tih mrtvih konekcija blokirala je prvi zahtev oko 10 sekundi, pre nego što bi pao sa porukom „Connection is not available”. Posetiocu je sajt jednostavno visio, pa bi se na kraju pojavila greška.
Zašto su Spring aplikacije najviše stradale
Spring Boot je popularan Java framework, a po podrazumevanim podešavanjima koristi pool konekcija po imenu HikariCP. Spring može da podesi taj pool preko podešavanja, uključujući koliko neaktivnih konekcija treba zadržati.
Ali Mythex svakom projektu daje bazu kao jednu promenljivu DATABASE_URL u obliku postgresql://user:pass@host/db. Spring ne može direktno da čita taj format. Zato su Spring aplikacije na Mythexu pravile sopstveni pool u kodu, parsirajući taj URL, a pool napravljen ručno ignoriše sva Springova spring.datasource.* podešavanja. I kada bi neko znao ispravna podešavanja pool-a, nigde ona ne bi bila primenjena.
Rešenje, prvi deo: podešavanja koja Spring može da koristi
Kada projekat ima bazu, sada mu dajemo i promenljive okruženja koje Spring čita sam:
SPRING_DATASOURCE_URL,SPRING_DATASOURCE_USERNAMEiSPRING_DATASOURCE_PASSWORD, pretvorene izDATABASE_URL(uz zahtevan SSL, osim ako URL kaže drugačije).- Podešavanja pool-a koja preživljavaju spavanje:
| Podešavanje | Vrednost | Zašto |
|---|---|---|
| Minimalan broj neaktivnih konekcija | 0 | Između zahteva ne držimo ništa otvoreno, pa nema šta da zastari |
| Vreme neaktivnosti | 30 sekundi | Brzo zatvara nekorišćene konekcije |
| Maksimalan životni vek | 2 minuta | Povlači svaku konekciju pre nego što može da zastari |
| Vreme čekanja na konekciju | 5 sekundi | Ne drži zahtev dugo ako baza sporo odgovara |
Bez držanja neaktivnih konekcija, probuđena aplikacija otvara jednu novu konekciju umesto da se probija kroz mrtve.
Kada su ove promenljive prisutne, Spring sam podešava pool, a podešavanja se primenjuju. Sve što je projekat sam podesio uvek ima prednost; mi popunjavamo samo ono što nedostaje. Aplikacije koje nisu Spring ignorišu ove promenljive.
Detalj zbog kojeg je skoro sve bilo uzalud
Spring preslikava promenljive okruženja na svoja podešavanja po pravilu koje je lako pogrešno razumeti. Podešavanje minimum-idle mora da se zapiše kao SPRING_DATASOURCE_HIKARI_MINIMUMIDLE, bez crtica i sa spojenim rečima. Ako se zapiše kao SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, što izgleda prirodnije, preslikava se na drugo, nepostojeće podešavanje (minimum.idle) i tiho se ignoriše.
To je greška koja prođe svaki pregled i ne uradi ništa u produkciji. Zato test proverava i da su vrednosti postavljene i da nijedna promenljiva ne koristi oblik sa donjim crtama.
Rešenje, drugi deo: svi ostali stekovi
Spring nije jedini framework sa pool-om, a ne možemo unapred da podesimo svaku biblioteku u svakom jeziku. Zato Mythex agent, AI koji piše vašu aplikaciju, sada za bilo koji stek dobija stalno uputstvo: objavljene aplikacije i njihove baze spavaju kada su neaktivne, pa konekcija koja je bila otvorena može biti mrtva pri sledećem zahtevu. Treba da:
- ne drži neaktivne konekcije ka bazi otvorene, ili proveri svaku pre upotrebe,
- jednom ponovi zahtev pri grešci konekcije, i
- koristi podešavanja baze koja platforma stavlja u okruženje, umesto da pravi sopstveni pool parsirajući
DATABASE_URL.
Poslednja tačka zatvara krug sa prvim delom: aplikacija napravljena na osnovu ponuđenih podešavanja automatski preuzima konfiguraciju koja je otporna na spavanje.
Rezultat
Izmereno na hosting platformi na kojoj pokrećemo objavljene aplikacije, prvi zahtev posle buđenja smanjen je sa 12,7 sekundi na 2,3 sekunde.
Šta smo iz ovoga izvukli
- Svaki sloj koji spava mora da se slaže oko toga šta preživljava. Zamrznuta aplikacija i uspavana baza napravile su svaka razuman izbor. Zajedno, aplikacija se probudila sa stanjem koje više nije bilo tačno.
- Podrazumevana podešavanja napravljena za servere koji su uvek uključeni ne odgovaraju aplikacijama koje se skaliraju na nulu. Održavanje konekcija toplim je dobra ideja, dok sve oko njih ne ohladi.
- Dajte framework-ima podatke u njihovom formatu. Jedan URL nama je bio jednostavan, ali je svaku Spring aplikaciju primoravao da ručno pravi pool koji ignoriše sopstvenu konfiguraciju.
- Testirajte da je podešavanje napisano onako kako ga framework čita. Ispravna vrednost 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š tekst o tome šta je Postgres.