Paggising ng Databases Nang Walang Patay na Connection
Ang mga na-publish na app sa Mythex, at ang kanilang mga database, ay natutulog kapag walang gumagamit. Kapag nagigising ang app, maaari nitong hawakan ang unang request nang 10 hanggang 12 segundo, dahil sinusubukan nitong gamitin muli ang mga database connection na namatay habang natutulog ang lahat. Ngayon, binibigyan namin ang mga Spring Boot app ng database settings na ligtas kahit pagkatapos ng sleep, at sinasabihan namin ang agent na bumuo ng mga app ng anumang stack sa parehong paraan. Sa hosting platform, bumaba ang unang request pagkatapos ng wake mula 12.7 segundo patungong 2.3 segundo.
Bakit natutulog ang mga app at database
Tumatakbo ang isang na-publish na Mythex app sa makinang nagsa-suspend pagkatapos ng ilang minutong idle, at ang database nito ay serverless Postgres na natutulog pagkatapos ng limang minutong idle at nagigising sa susunod na request. Iyon ang nagpapamura sa tahimik na app: sinisingil ka para sa kung ano ang aktwal na nagamit ng database, at ang natutulog na app ay walang nagagastos sa compute. Isinulat namin ang tungkol sa panig ng billing sa pagbibilang ng databases ayon sa aktwal nilang nagamit.
Ang problema ay magkahiwalay na natutulog ang dalawa, at hindi sila sumasang-ayon kung ano ang isang connection.
Ang sintomas: mabagal na unang bisita
Karaniwang may connection pool ang mga server app: ilang bukas na database connection na nakahanda, para hindi magbayad ng gastos sa pagbubukas ng bago ang bawat request. Tamang disenyo iyon para sa app na laging gising.
Narito ang nangyayari sa sleep:
- Tumatakbo ang app, may ilang idle na connection sa pool nito.
- Walang bumibisita. Nagsa-suspend ang makina ng app, nakapirmi, buo pa ang pool nito.
- Natutulog ang database at binibitawan ang dulo nito ng bawat connection.
- May dumating na bisita. Gumising ang app na eksaktong ganoon pa rin ang estado, hawak pa rin ang mga connection na hindi na kilala ng database.
- Ibinibigay ng pool ang isa sa mga patay na connection na iyon. Kailangan muna nitong malaman na patay na ito, sa pamamagitan ng pagsubok dito at paghihintay, bago ito isuko.
Sa Spring Boot app, ang pag-validate sa mga patay na connection na iyon ay humarang sa unang request nang humigit-kumulang 10 segundo bago ito pumalpak na may "Connection is not available". Para sa bisita, parang nag-hang lang ang site, at pagkatapos ay baka magpakita ng error.
Bakit pinakamalala ang Spring apps
Sikat na Java framework ang Spring Boot, at gumagamit ito ng connection pool na tinatawag na HikariCP bilang default. Maaaring i-configure ng Spring ang pool na iyon mula sa settings, kasama kung ilang idle connection ang itatago.
Pero binibigyan ng Mythex ang bawat app ng database nito bilang iisang DATABASE_URL sa anyong postgresql://user:pass@host/db. Hindi ito diretsong mabasa ng Spring. Kaya ang mga Spring app na nakabase sa Mythex ay gumagawa ng sarili nilang pool sa code sa pamamagitan ng pag-parse sa URL na iyon, at ang pool na gawa sa kamay ay binabalewala ang lahat ng spring.datasource.* settings ng Spring. Kahit alam ng isang tao ang tamang pool settings, wala namang lugar kung saan ito magkakabisa.
Ang ayos, bahagi 1: settings na kayang gamitin ng Spring
Kapag may database ang project, binibigyan na rin namin ito ng environment variables na natural na binabasa ng Spring:
SPRING_DATASOURCE_URL,SPRING_DATASOURCE_USERNAMEatSPRING_DATASOURCE_PASSWORD, na kino-convert mula saDATABASE_URL(may kinakailangang SSL maliban kung iba ang sinasabi ng URL).- Mga pool setting na nakakaligtas sa sleep:
| Setting | Halaga | Bakit |
|---|---|---|
| Minimum idle connections | 0 | Walang bukas na connection sa pagitan ng mga request, kaya walang maaaring maging lipas |
| Idle timeout | 30 segundo | Isara agad ang hindi nagagamit na connection |
| Maximum lifetime | 2 minuto | Iretiro ang bawat connection bago pa ito tumanda |
| Connection timeout | 5 segundo | Huwag bitinin nang matagal ang request kung mabagal sumagot ang database |
Dahil walang idle na connection na hawak, ang app na nagising ay magbubukas ng isang bagong connection sa halip na dumaan sa mga patay.
Kapag nandiyan ang mga variable na ito, ang Spring na mismo ang nag-co-configure ng pool, at nagkakabisa ang mga settings. Laging nananalo ang anumang itinakda na ng project; pinupunan lang namin ang kulang. Hindi pinapansin ng mga hindi-Spring na app ang mga variable na ito.
Ang detalyeng halos wala nang silbi
Iniuugnay ng Spring ang environment variables sa mga setting nito ayon sa patakarang madaling magkamali. Dapat isulat ang setting na minimum-idle bilang SPRING_DATASOURCE_HIKARI_MINIMUMIDLE, walang gitling, pinagsamang mga salita. Kapag isinulat ito bilang SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, na mukhang mas natural, nagma-map ito sa ibang setting na hindi umiiral (minimum.idle) at tahimik na binabalewala.
Ito ang uri ng pagkakamaling pumapasa sa bawat review at walang nagagawa sa production. Kaya may test na nagche-check kapwa na nakatakda ang mga halaga at na walang variable na gumagamit ng anyong pinaghihiwalay ng underscore.
Ang ayos, bahagi 2: bawat ibang stack
Hindi lang ang Spring ang framework na may pool, at hindi namin kayang i-pre-configure ang bawat library sa bawat wika. Kaya ang Mythex agent, ang AI na sumusulat ng app mo, ay may permanenteng tagubilin na ngayon para sa anumang stack: natutulog ang mga na-publish na app at ang kanilang mga database kapag idle, kaya maaaring patay na ang connection na nanatiling bukas sa susunod na request. Dapat itong:
- huwag magpanatiling bukas ng idle na database connection, o suriin muna ang bawat isa bago gamitin,
- subukan muli nang isang beses kapag may error sa connection, at
- gamitin ang database settings na ibinibigay ng platform sa environment, sa halip na bumuo ng sarili nitong pool sa pamamagitan ng pag-parse ng
DATABASE_URL.
Ang huling puntong iyan ay nagsasara ng loop kasama ng bahagi 1: ang app na binuo gamit ang ibinigay na settings ay awtomatikong nakukuha ang sleep-safe na configuration.
Ang resulta
Sa hosting platform na pinapatakbuhan namin ng mga na-publish na app, bumaba ang unang request pagkatapos ng wake mula 12.7 segundo patungong 2.3 segundo.
Ang natutunan namin
- Dapat magkasundo ang bawat layer na natutulog kung ano ang nananatili. Parehong makatwiran ang pagpili ng nakapirmi na app at ng natutulog na database. Magkasama, ang app ay nagising na may hawak na estadong hindi na totoo.
- Ang mga default na dinisenyo para sa laging-gising na server ay hindi bagay sa mga app na nag-i-scale sa zero. Maganda ang pagpapanatiling mainit ng mga connection hanggang sa lumamig ang lahat ng nakapaligid dito.
- Ibigay sa framework ang datos nito sa sarili nitong format. Simple para sa amin ang isang URL, pero pinilit nito ang bawat Spring app na gumawa ng sariling pool na binabalewala ang sarili nitong configuration.
- Subukan na tama ang spelling ng setting ayon sa pagbasa ng framework. Tamang halaga sa maling pangalan ay walang nagagawa, nang tahimik.
Kung bago ka sa paraan ng paggana ng mga database sa Mythex, tingnan ang database docs at ang aming paliwanag tungkol sa ano ang Postgres.