Prebujanje baz brez mrtvih povezav
Objavljene aplikacije na platformi Mythex in njihove baze podatkov gredo spat, kadar jih nihče ne uporablja. Ko se je aplikacija prebudila, je lahko prvo zahtevo držala 10–12 sekund, ker je poskušala ponovno uporabiti povezave do baze, ki so med mirovanjem vsega odmrle. Zdaj Spring Boot aplikacijam dajemo nastavitve baze, ki so varne po spanju, in agentu naročimo, naj vse aplikacije gradi na enak način, ne glede na sklad. Na gostiteljski platformi se je prva zahteva po prebujanju skrajšala z 12,7 sekunde na 2,3 sekunde.
Zakaj aplikacije in baze spijo
Objavljena aplikacija na platformi Mythex teče na stroju, ki se po nekaj minutah mirovanja uspava. Njena baza podatkov je serverless Postgres, ki zaspi po petih minutah mirovanja in se prebudi ob naslednji poizvedbi. Prav to ohranja tiho aplikacijo poceni: plačate za to, kar baza dejansko porabi, uspavana aplikacija pa ne porablja ničesar za računanje. O vidiku obračunavanja smo pisali v članku obračunavanje baz podatkov glede na to, kaj dejansko porabijo.
Ulov je v tem, da se obe uspavata ločeno in se ne strinjata, kaj je povezava.
Simptom: počasen prvi obisk
Večina strežniških aplikacij vzdržuje connection pool: nekaj odprtih povezav do baze, ki so pripravljene, da zahtevek ne plača stroška odpiranja nove. To je pravilna zasnova za aplikacijo, ki je vedno vklopljena.
Pri spanju se zgodi naslednje:
- Aplikacija teče, z nekaj neaktivnimi povezavami v poolu.
- Nihče je ne obišče. Stroj aplikacije se uspe, zamrznjen, pool pa ostane nedotaknjen.
- Baza zaspi in na svoji strani zapre vsako povezavo.
- Obiskovalec pride. Aplikacija se prebudi točno tako, kot je bila, še vedno z več povezavami, ki jih baza ne pozna več.
- Pool dodeli eno od teh povezav. Ta mora ugotoviti, da je mrtva, tako da jo poskusi uporabiti in čaka, preden jo opusti.
V aplikaciji Spring Boot je validacija teh mrtvih povezav blokirala prvi zahtevek približno 10 sekund, preden je odpovedal z napako »Connection is not available«. Za obiskovalca je bilo videti, kot da se stran zatakne, nato pa morda pokaže napako.
Zakaj so Spring aplikacije najbolj trpele
Spring Boot je priljubljen Java framework, ki privzeto uporablja connection pool HikariCP. Spring lahko ta pool konfigurira iz nastavitev, vključno s tem, koliko neaktivnih povezav ohrani.
Platforma Mythex pa vsaki aplikaciji da bazo kot eno samo spremenljivko DATABASE_URL v obliki postgresql://user:pass@host/db. Spring tega formata ne more neposredno prebrati. Zato so Spring aplikacije na platformi Mythex sestavljale lasten pool v kodi, tako da so razčlenile ta URL. Pool, sestavljen ročno, pa ignorira vse nastavitve spring.datasource.*. Tudi če bi nekdo poznal prave nastavitve poola, ne bi imele nikjer učinka.
Popravek, 1. del: nastavitve, ki jih Spring lahko uporabi
Kadar ima projekt bazo, mu zdaj dodatno dodelimo spremenljivke okolja, ki jih Spring bere neposredno:
SPRING_DATASOURCE_URL,SPRING_DATASOURCE_USERNAMEinSPRING_DATASOURCE_PASSWORD, pretvorjene izDATABASE_URL(SSL je zahtevan, razen če URL navaja drugače).- Nastavitve poola, ki preživijo spanje:
| Nastavitev | Vrednost | Zakaj |
|---|---|---|
| Najmanj neaktivnih povezav | 0 | Med zahtevki ne drži nič odprtega, zato ni ničesar, kar bi lahko zastarelo |
| Časovna omejitev neaktivnosti | 30 sekund | Nepotrebne povezave hitro zapre |
| Največja življenjska doba | 2 minuti | Vsako povezavo upokoji, preden lahko postane stara |
| Časovna omejitev povezave | 5 sekund | Zahtevka ne zadrži dolgo, če baza počasi odgovarja |
Ker ni ohranjenih neaktivnih povezav, prebujena aplikacija odpre eno novo povezavo, namesto da bi se prebijala skozi mrtve.
Ko so te spremenljivke prisotne, Spring pool konfigurira sam in nastavitve veljajo. Karkoli je projekt sam nastavil, vedno zmaga. Mi dopolnimo le manjkajoče. Aplikacije, ki niso Spring, te spremenljivke ignorirajo.
Podrobnost, ki je skoraj naredila nič
Spring preslikuje spremenljivke okolja v svoje nastavitve po pravilu, ki ga je enostavno zgrešiti. Nastavitev minimum-idle mora biti zapisana kot SPRING_DATASOURCE_HIKARI_MINIMUMIDLE, vezaji izpadejo, besede so zlepljene. Zapis SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, ki se zdi bolj naraven, se preslika v drugo, neobstoječo nastavitev (minimum.idle) in je neopazno prezrt.
Takšna napaka gre skozi vsak pregled in v produkciji ne naredi ničesar. Zato test preveri, da so vrednosti nastavljene in da nobena spremenljivka ne uporablja zapisa z veznikom podčrtaj.
Popravek, 2. del: vsi drugi skladi
Spring ni edini framework s poolom, in ne moremo vnaprej konfigurirati vsake knjižnice v vsakem jeziku. Zato je agent Mythex, AI, ki piše vašo aplikacijo, zdaj dobil stalno navodilo za vsak sklad: objavljene aplikacije in njihove baze zaspijo, ko so neaktivne, zato povezava, ki je bila odprta, ob naslednji zahtevi lahko ne deluje več. Agent mora:
- ne držati odprtih neaktivnih povezav do baze ali pa preveriti vsako pred uporabo,
- ob napaki pri povezavi poskusiti enkrat znova in
- uporabiti nastavitve baze, ki jih platforma poda v okolju, namesto da bi sam sestavljal pool z razčlenjevanjem
DATABASE_URL.
Zadnja točka zaključi krog s prvim delom: aplikacija, zgrajena na zagotovljenih nastavitvah, samodejno prevzame konfiguracijo, varno za spanje.
Rezultat
Izmerjeno na gostiteljski platformi, na kateri zaganjamo objavljene aplikacije, se je prva zahteva po prebujanju skrajšala z 12,7 sekunde na 2,3 sekunde.
Kaj smo iz tega izvlekli
- Vsaka plast, ki spi, se mora strinjati, kaj preživi. Zamrznjena aplikacija in uspavana baza sta vsaka sprejela razumno odločitev. Skupaj se je aplikacija prebudila z zastarelim stanjem, ki ni več veljalo.
- Privzete nastavitve za strežnike, ki so vedno vklopljeni, ne ustrezajo aplikacijam, ki se skalirajo na nič. Ohranjanje povezav toplih je dobra zamisel, dokler vse okoli njih ne ohladi.
- Dajte frameworkom njihove podatke v njihovem formatu. En URL je bil za nas preprost, a je vsako Spring aplikacijo prisilil, da ročno sestavi pool, ki je ignoriral lastno konfiguracijo.
- Preverite, da je nastavitev zapisana tako, kot jo framework bere. Pravilna vrednost pod napačnim imenom tiho ne naredi ničesar.
Če se šele seznanjate z delovanjem baz na platformi Mythex, si oglejte dokumentacijo o bazah in našo razlago, kaj je Postgres.