Blogi

Kuidas üks raske vestlus oleks võinud API maha võtta

  1. septembril, umbes 17 minutit pärast väljalaset, jooksid mõlemad meie tootmise API serverid samal hetkel mälust välja, taaskäivitusid ja umbes viie minuti jooksul ei olnud koormustasakaalurile ühtegi tervet serverit, kuhu liiklust saata. Esimene parandus andis API-le kaks korda rohkem mälu. Tegelik põhjus selgus hiljem samal päeval: ühe konkreetse vestluse avamine palus API-l laadida ühe päringuga 53 MB sõnumeid. Vestluste ajalugu laaditakse nüüd lehtedena, mida piirab suurus, mitte ainult arv, ja see vestlus avaneb 5 MB esimese lehega, mitte krahhiga.

Mis läks alla

Meie API töötab konteinerina kummaski kahest serverist, mille ees on koormustasakaaluri. Igal konteineril oli mälupiir 384 MiB. Puhkeolekus kasutab see 130–140 MiB, nii et piir tundus piisava varuga.

Mõlemad konteinerid jõudsid piirini korraga ja jooksid kokku teatega „JavaScript heap out of memory“. Heap on mälu, mida Node.js protsess kasutab töötavate objektide hoidmiseks. Kuna mõlemad serverid ebaõnnestusid korraga, ei jäänud kuhugi päringuid suunata. See on kõige halvem katkestus kahe serveriga seadistusele: redundantsus aitab ainult siis, kui tõrked ei tule samal ajal.

Esimene parandus: rohkem ruumi

Ajastus viitas väljalaskele. Pärast väljalaset jätkatakse agendikäike, mida väljalase katkestas, ja need salvestavad oma kirjad uuesti — ja see tööpuhang tundus ilmse mälutipu allikana.

Seega tõstsime esimeses muudatuses API piiri 384 MiB-lt 768 MiB-le. Rakendasime selle samal päeval mõlemal serveril otse ja kinnitasime selle ka juurutuse seadistusse, et järgmine juurutus ei viiks 384 tagasi. Käsitsi tehtud parandus serveris, mille järgmine juurutus tagasi keerab, on tavaline viis, kuidas sama katkestus tagasi tuleb.

Rohkem mälu oli mõistlik turvavaru. See ei olnud selgitus.

Tegelik põhjus: üks päring, 71 MB

Hiljem samal päeval reprodutseerisime krahhi vestlusest tehtud koopial, kasutades tootmise vana mälupiiri. Koopia krahhistas API ise, ilma juurutuseta.

Projekti avamisel küsib veebirakendus API-lt vestluse ajalugu. Lõpp-punkt tagastas uusimad 30 sõnumit tervena. Enamiku vestluste puhul on 30 sõnumit väike hulk. Selle vestluse uusimad 30 sõnumit olid andmebaasis 53 MB ja vastus 71 MB. Mitu agendi vastust oli 4–10 MB, peamiselt alamagentide väljavõtted: abiagendid, mida peamine agent käivitab, et töötada osa ülesandest paralleelselt, ja kelle täielik töö salvestatakse vastuse juurde.

Selle ühe vastuse koostamine kulutas rohkem heap'i, kui API-l oli. Ja iga projekti avamine või värskendamine saatis päringu uuesti. Üks vestlus võis krahhistada selle serveri, kuhu ta jõudis, ja kuna lehe võis uuesti laadida, võis see jõuda mõlemani.

„30 sõnumit“ ei olnud kunagi tegelik suuruspiir. See oli arvupiir, mis oli tavaliste vestluste jaoks lihtsalt väike.

Parandus: lehed, mida piirab suurus ja arv

Ajaloo leht on nüüd 30 sõnumit või umbes 4 MB sõnumeid, olenevalt sellest, mis tuleb enne.

See töötab kahes sammus:

  1. Küsi kõigepealt suurused. API küsib andmebaasilt uusimate sõnumite ID-d ja salvestatud suurused, ilma sisuta. See päring on odav, olenemata sellest, kui suured sõnumid on.
  2. Lae ainult see, mis mahub. Uusimast vanimani liikudes lisab see sõnumeid, kuni järgmine ületaks lehe 4 MB piiri. Ainult need read laaditakse siis täielikult.

Kaks reeglit hoiavad selle ohutuna:

  • Uusim sõnum läheb alati lehele, olenemata suurusest. Leht, mis ei tagastaks midagi, jätaks vestluse kinni, ilma võimaluseta tagasi kerida.
  • Midagi ei lõigata. Ükski sõnum ei lühendata ega jäeta välja. Ülejäänud vestlus laaditakse juba olemasoleva „Scroll up for earlier messages“ juhtimise kaudu, mis vanematele sõnumitele juba kasutati, ühe lehe kaupa.

Leidsime veel ühe koha, millel on sama kuju. Kui peatad käigu, kontrollib API viimaseid vastuseid, et näha, kas mõni on tühi ja tuleks puhastada. See laadis selleks kaheksa tervet sõnumit. Mitme megabaidise vastusega vestluses on see sama probleem väiksemal kujul. Nüüd küsib API andmebaasilt jah-või-ei küsimuse — kas sellel sõnumil on sisu? — ilma sisu ennast laadimata.

Kuidas me kontrollisime

Koopial vestlusest, mis töötas vana 384 MiB piiriga:

  • Esimene leht on 5 MB. Varem krahhistas sama päring API.
  • Viis brauseri vahelehte, mis avavad vestluse korraga, tipnevad 154 MB mälus.
  • Kogu vestluse kerimine tagasi toob kõik 190 sõnumit, igaüks täpselt üks kord, õiges järjekorras.

Lehtede valimise loogikal on ka ühiktestid, sealhulgas üks, mis on ehitatud selle vestluse uusimate sõnumite päris suuruste järgi. Esimene leht tuleb ühe sõnumiga, ütleb, et on veel, ja järgmine leht algab sellele järgnevast.

Mida sellest õppisime

  • Arv ei ole suuruspiir. Iga lõpp-punkt, mis tagastab „uusimad N“ midagi, mis võib piiramatult kasvada, vajab ka baidieelarvet. Andmed leiavad selle lünga varem või hiljem.
  • Ilmne kahtlusalune ei ole alati põhjus. Väljalase oli tõeline käivitaja täiendavale tööle ja rohkem mälu oli väärt. Aga krahh reprodutseeriti ilma juurutuseta, ja ilma reprodutseerimiseta oleksime peatunud mälu suurendamisel.
  • Kaks serverit kukuvad koos, kui nad saavad sama päringu. Redundantsus kaitseb ühe serveri surma eest. See ei kaitse päringu eest, mis tapab iga serveri, kuhu see jõuab, eriti kui kasutaja proovib seda lihtsalt lehte värskendades uuesti.
  • Paranda seadistuses, mitte ainult masinas. Mälu suurendus läks samal päeval juurutuse seadistusse, nii et järgmine juurutus seda ei kaotanud.

See on meie teine hiljutine mälulugu, mis puudutab agendi väljundit. Esimene oli edenemissilt, mis järjestas 690 MB stringe. Kui kasutad Mythexis alamagendeid, saad lugeda nende toimimisest dokumentatsioonist.

Mythex · Pricing · Ehita kõike AI-ga · Veebilehtede ja rakenduste mallid · Mythex võrdluses · Tehisintellektiga rakenduste ehitamise sõnastik · Tasuta tööriistad tehisintellektiga rakenduste ehitamiseks · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)