
Päev, mil meie rakendus tegi endale DDoS-i
Ootel olevate üleslaadimiste kuhi, mis käivitumisel korraga vabaks lasti, muutis iga GeekBye kliendi väikeseks teenusetõkestuse (DoS) rünnakuks meie enda serverite vastu. Parandus — ja ühenduse elususe redel, mille see meid ehitama sundis — on üks kasulikumaid asju, mida v2 meile õpetas.
Iga hajussüsteemide insener kohtab varem või hiljem thundering herdi — tormavat karja: klientide massi, kes kõik teevad sama asja samal hetkel, ja jagatud ressurssi nende taga, mis vajub kokku. Tavaliselt on need kellegi teise kliendid. GeekBye v2.0.1 puhul olid need meie omad, ja ründaja oli meie enda rakendus.
Kuidas märkmik ründab iseennast
GeekBye saab üles laadida salvestisi sinu Google Drive'i. Kui salvestist ei saa kohe üles laadida — sa olid võrguühenduseta, rakendus sulgus, Drive tõrkus — läheb see kuhja, et hiljem uuesti proovida. Mõistlik.
Rike oli selles, millal "hiljem" saabus. Järgmisel käivitusel püüdis rakendus kogu kuhja tühjendada korraga. Üks kasutaja nädalase ootel salvestiste varuga muutus samaaegsete üleslaadimispäringute pursaks sel hetkel, kui ta rakenduse avas. Korruta iga kasutajaga, kes hommikul rakenduse käivitab, ja meie taustsüsteemilt nõuti autentimist, kiiruse kontrollimist ja liiklusseina töötlemist samade paari sekundi jooksul — klientidelt, kes kõik tehniliselt käitusid õigesti.
Meie taustsüsteem tegi õige asja ja piiras üleujutuse kiirust. Ja just seal algas teise järgu kahju. Kiirusepiirangu vastus on HTTP 429, ja 429 sarnaneb väga teiste rikketega, kui sa ei ole ettevaatlik:
- Käivituse profiili pärimine sai
429ja rakendus käsitles seda kui autentimine ebaõnnestus — logides kasutajaid korraks välja täiesti kehtivast seansist. - Transkriptsiooniühendus sai üldise
429ja näitas helipiiri saavutamise uuenduse teadet — teatades maksvatele kasutajatele, et nad on jõudnud kvoodini, milleni nad polnud jõudnud.
Nii et üks juurpõhjus — tempimata kuhi — tekitas kolm nähtavat sümptomit: serverikoormuse, valed väljalogimised ja valed lisamüügid. Klassikaline ise-DoS-i kuju: koormus on halb, aga see, mida kasutajad tegelikult tunnevad, on koormuse sümptomite valesti tõlgendamine.
Parandus, kahes kihis
Peata torm. Üleslaadimiste kuhi on nüüd tempitud — päringud on laiali jaotatud taganemisega, ja jahtumisperiood pärast iga 429, nii et klient taandub pingul serverist, mitte ei nõju sellele veel rohkem. Thundering herdist saab korralik järjekord.
Peata vale tõlgendamine. Mööduv 429 või 5xx käivituse ajal ei logi sind enam välja — klient eristab "server on korraks hõivatud" ja "sinu seanss on kehtetu" vahel. Ja üldine kiirusepiirangu 429 transkriptsiooniteel ei teeskle enam helikvoodi viga; ainult tõeline kvoodivastus näitab uuenduse teadet. Õppetund, mis jäi külge: veakood ei ole vea tähendus. 429 tähendab "aeglusta", mitte "sa ei ole volitatud" ega "sul on kvoot otsas" — ja klient peab vahet teadma.
Elususe redel, mis järgnes
Karja tempimine paljastas vaiksema probleemi: kui ühendus koormuse all tõesti halvaks läks, kui kiiresti me seda märkasime? Aeglasemalt, kui tahtsime. Nii et v2.0.4 ehitas välja ühenduse elususe redeli reaalajas transkriptsiooni jaoks:
- Südamelöögid — transkriptsioonisoklile saadetakse ping fikseeritud intervalliga, nii et vaikselt surnud ühendus tuvastatakse sekunditega, mitte oodates, kuni järgmine helitükk ebaõnnestub.
- Võrgu-taastumise taasühendumise tõuge — kui OS teatab, et võrk on tagasi, taasloob rakendus ühenduse ennetavalt, mitte ei oota, et sellele juhuslikult otsa komistada.
- Juht-ping/pongi elusus — rakendusetasandi edasi-tagasi kontroll, mis kinnitab mitte ainult "sokkel on avatud", vaid "teine ots tõesti vastab".
- Teenusele kuuluv taasühendumise värav — üks koht otsustab, kas uuesti ühenduda, mitte mitu rakenduse osa võistlemas seda tegema ja teineteise otsa astumas.
Miski sellest ei ole glamuurne. Kõik see on põhjus, miks v2 seanss tundub, nagu see lihtsalt... jääks ühendatuks.
See juhtus sellel nädalal taas — üks aste allpool
Siin on osa, mis teeb sellest enama kui sõjaloo. Sama rikkeklass ilmus taas mõni päev tagasi, üks tasand meist allpool. Üks klient tulistas 21 transkriptsiooniseansi algust vähem kui 400 millisekundiga — ja komistas meie kõnepakkuja konto ülese piirangu, 15 samaaegse päringu, otsa. Torm jagatud taristu vastu, täpselt nagu üleslaadimiste kuhi, ainult suunatud sõltuvusele, mitte meie enda taustsüsteemile.
Kuju on identne, ja nii on ka parandus: tormav klient vajab single-flight kaitset, et ta ei saaks tulistada kahtkümmet algust ühe kavatsuse jaoks, ja jagatud ressurss vajab kasutajapõhist ülempiiri, et üks klient ei saaks kogu basseini ära kulutada. Me oleme selle kliendipoolse versiooni varem ehitanud — üleslaadimiste tempija on see muster. Nüüd rakendame seda seansi alustamistele. Thundering herd ei ole viga, mille parandad ühe korra; see on kuju, mille õpid ära tundma kõikjal, kus kliendid kohtavad jagatud piirangut.
Kolm asja, mida kaasa võtta
- Sinu enda kliendid on koormustest, mida sa ei planeerinud. Kõik, mis käivitamisel kimpu paneb, käivitusel uuesti proovib või ärkamisel taasühendub, on thundering herd, mis ootab piisavat kasutajate hulka. Tempi seda enne, kui neid on.
- Erista kood tähendusest.
429on kõige valemini loetud staatus, mis olemas on. "Aeglusta" ei ole "logi välja" ega "maksa meile". Suuna iga rike sinna, mida see tegelikult tähendab. - Elusus on redel, mitte lipuke. "Kas ühendus on elus?" küsimusel on mitu ausat vastust eri kihtides — sokkel avatud, baidid voolamas, teine ots vastamas, võrk kohal. Töökindel rakendus kontrollib rohkem kui üht.
See on see glamuuritu masinavärk GeekBye v2 rahu all. Töökindlusfunktsioonide kohta, mille see võimaldas, vaata miks su AI-märkmik peatub halva Wi-Fi korral ja reaalajas transkriptsioon, kui tulemüür blokeerib WebSockets (v2.0.8). Selle sarja naaberväljalasete kohta miks su AI-märkmik lõpetab salvestamise keset koosolekut (v2.0.9).