Duomenų bazių pabudimas be negyvų ryšių
Publikuotos Mythex programėlės ir jų duomenų bazės užmiega, kai niekas jų nenaudoja. Kai programėlė pabunda, pirmą užklausą ji galėjo laikyti 10–12 sekundžių, nes bandė naudoti duomenų bazės ryšius, kurie nutrūko, kol viskas miegojo. Dabar Spring Boot programėlėms suteikiame duomenų bazės nustatymus, saugius po miego, ir nurodome agentui kurti bet kokio steko programėles tuo pačiu būdu. Hosting platformoje pirmoji užklausa po pabudimo sumažėjo nuo 12,7 sekundės iki 2,3 sekundės.
Kodėl programėlės ir duomenų bazės miega
Publikuota Mythex programėlė veikia mašinoje, kuri sustabdoma po kelių neaktyvių minučių, o jos duomenų bazė – serverless Postgres, kuri užmiega po penkių neaktyvių minučių ir pabunda su kita užklausa. Būtent tai laiko tylią programėlę pigią: mokate už tai, ką duomenų bazė iš tikrųjų panaudojo, o miegančia programėlė neišleidžia nieko skaičiavimams. Apie atsiskaitymo pusę rašėme straipsnyje atsiskaityti už duomenų bazes pagal tai, ką jos iš tikrųjų naudoja.
Problema ta, kad abu užmiega atskirai ir nesutaria, kas yra ryšys.
Simptomas: lėtas pirmas apsilankymas
Dauguma serverio programėlių laiko ryšių baseiną (connection pool): kelis atvirus duomenų bazės ryšius, paruoštus iš anksto, kad kiekviena užklausa nemokėtų už naujo ryšio atidarymą. Tai tinkamas dizainas programėlei, kuri visada veikia.
Štai kas nutinka su miegu:
- Programėlė veikia, o jos baseine yra keli neaktyvūs ryšiai.
- Niekas neapsilanko. Programėlės mašina sustabdoma – užšalusi, su nepakitusiu baseinu.
- Duomenų bazė užmiega ir nutraukia savo pusę kiekvieno ryšio.
- Atvyksta lankytojas. Programėlė pabunda tokia, kokia buvo, vis dar laikydama ryšius, kurių duomenų bazė nebeatpažįsta.
- Baseinas išduoda vieną iš tų ryšių. Prieš jį atsisakydamas, reikia sužinoti, kad jis negyvas – jį išbandant ir laukiant.
Spring Boot programėlėje negyvų ryšių patikrinimas blokavo pirmą užklausą apie 10 sekundžių, o tada ji nepavykdavo su „Connection is not available“. Lankytojui svetainė tiesiog užstrigdavo, o paskui galbūt parodydavo klaidą.
Kodėl Spring programėlėms tai buvo blogiausia
Spring Boot yra populiari Java sistema, ir pagal numatytuosius nustatymus ji naudoja ryšių baseiną HikariCP. Spring gali sukonfigūruoti tą baseiną pagal nustatymus, įskaitant tai, kiek neaktyvių ryšių laikyti.
Bet Mythex kiekvienai programėlei duomenų bazę suteikia kaip vieną DATABASE_URL kintamąjį formatu postgresql://user:pass@host/db. Spring tiesiogiai to formato neskaito. Todėl Spring programėlės Mythex platformoje patys sudarydavo baseiną kode, išnagrinėdamos tą URL – o rankiniu būdu sudarytas baseinas ignoruoja visus Spring spring.datasource.* nustatymus. Net jei kas nors žinojo tinkamus baseino nustatymus, nebuvo vietos, kur jie įsigaliotų.
Pataisa, 1 dalis: nustatymai, kuriuos Spring gali naudoti
Kai projektas turi duomenų bazę, dabar jam taip pat suteikiame aplinkos kintamuosius, kuriuos Spring skaito natūraliai:
SPRING_DATASOURCE_URL,SPRING_DATASOURCE_USERNAMEirSPRING_DATASOURCE_PASSWORD, konvertuoti išDATABASE_URL(su reikalingu SSL, nebent URL nurodo kitaip).- Baseino nustatymai, kurie išlieka po miego:
| Nustatymas | Reikšmė | Kodėl |
|---|---|---|
| Mažiausias neaktyvių ryšių skaičius | 0 | Tarp užklausų neatidarinėti nieko, todėl nėra ko senti |
| Neaktyvumo laikas | 30 sekundžių | Greitai uždaryti nenaudojamus ryšius |
| Maksimali trukmė | 2 minutės | Pakeisti kiekvieną ryšį, kol jis nesensta |
| Ryšio laiko limitas | 5 sekundės | Neblokuoti užklausos ilgai, jei duomenų bazė lėtai atsako |
Kai neturime jokių neaktyvių ryšių, atsibudusi programėlė atidaro vieną naują ryšį, o ne braidžioja per negyvus.
Kai šie kintamieji yra, Spring pats sukonfigūruoja baseiną, ir nustatymai įsigalioja. Tai, ką projektas pats yra nustatęs, visada laimi – mes užpildome tik tai, kas trūksta. Ne Spring programėlės šiuos kintamuosius ignoruoja.
Detalė, kuri beveik nieko nepakeitė
Spring aplinkos kintamuosius priskiria savo nustatymams taisykle, kurią lengva supainioti. Nustatymas minimum-idle turi būti užrašytas kaip SPRING_DATASOURCE_HIKARI_MINIMUMIDLE – brūkšneliai išmesti, žodžiai sujungti. Užrašius SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, kas atrodo natūraliau, jis priskiriamas kitam, neegzistuojančiam nustatymui (minimum.idle) ir tyliai ignoruojamas.
Tokia klaida praeina bet kokią peržiūrą ir nieko nepakeičia gamyboje. Todėl testas tikrina, ar reikšmės nustatytos, ir ar nė vienas kintamasis nenaudoja brūkšnelių atskirtos formos.
Pataisa, 2 dalis: visi kiti steko
Spring nėra vienintelė sistema su baseinu, ir negalime iš anksto sukonfigūruoti kiekvienos bibliotekos kiekvienoje kalboje. Todėl Mythex agentas – AI, kuris rašo jūsų programėlę – dabar gauna nuolatinę instrukciją bet kuriam steko tipui: publikuotos programėlės ir jų duomenų bazės užmiega, kai neaktyvios, todėl ryšys, paliktas atviras, kitą kartą gali būti negyvas. Jis turėtų:
- neišlaikyti jokių neaktyvių duomenų bazės ryšių atidarytų arba patikrinti kiekvieną prieš naudojant,
- vieną kartą pakartoti bandymą, jei įvyksta ryšio klaida, ir
- naudoti platformos aplinkoje pateiktus duomenų bazės nustatymus, o ne kurti savo baseiną išnagrinėjant
DATABASE_URL.
Pastarasis punktas užbaigia ciklą su 1 dalimi: programėlė, sukurta naudojant pateiktus nustatymus, automatiškai gauna konfigūraciją, saugią po miego.
Rezultatas
Matuojant platformoje, kurioje paleidžiame publikuotas programėles, pirmoji užklausa po pabudimo sumažėjo nuo 12,7 sekundės iki 2,3 sekundės.
Ką iš to pasiėmėme
- Kiekvienas sluoksnis, kuris užmiega, turi sutarti, kas išlieka. Užšalusi programėlė ir miegantis duomenų bazė padarė kiekvienas pagrįstą pasirinkimą. Kartu programėlė pabudo laikydama būseną, kuri nebebuvo teisinga.
- Numatytieji nustatymai, sukurti nuolat veikiantiems serveriams, netinka programėlėms, kurios mastelį keičia iki nulio. Ryšių laikymas šiltai yra geras sumanymas, kol viskas aplinkui atvėsta.
- Duokite sistemoms jų duomenis jų pačių formatu. Vienas URL mums buvo paprastas, bet privertė kiekvieną Spring programėlę rankiniu būdu kurti baseiną, kuris ignoravo jos pačios konfigūraciją.
- Testuokite, ar nustatymas parašytas taip, kaip sistema jį skaito. Teisinga reikšmė neteisingu pavadinimu nieko nepadaro – tyliai.
Jei norite suprasti, kaip duomenų bazės veikia Mythex, žr. duomenų bazių dokumentaciją ir mūsų paaiškinimą kas yra Postgres.