Steven
Steven4 min lukuaika

Päivä, jona sovelluksemme teki DDoS-hyökkäyksen itseään vastaan

Odottavien latausten kertymä, joka vapautettiin kaikki kerralla käynnistyksessä, muutti jokaisen GeekBye-asiakkaan pieneksi palvelunestohyökkäykseksi (DoS) omia palvelimiamme vastaan. Korjaus — ja yhteyden elävyystikkaat, jotka se pakotti meidät rakentamaan — on yksi hyödyllisimmistä asioista, jotka v2 meille opetti.

Luotettavuus
Verkot
Ohjelmistokehitys
GeekBye-julkaisut
Päivä, jona sovelluksemme teki DDoS-hyökkäyksen itseään vastaan

Jokainen hajautettujen järjestelmien insinööri kohtaa ennemmin tai myöhemmin thundering herdin — ryntäävän lauman: joukon asiakkaita, jotka kaikki tekevät saman asian samalla hetkellä, ja niiden takana olevan jaetun resurssin, joka notkahtaa. Yleensä ne ovat jonkun toisen asiakkaita. GeekBye v2.0.1:ssä ne olivat meidän, ja hyökkääjä oli oma sovelluksemme.

Miten muistiinpanotyökalu hyökkää itseään vastaan

GeekBye voi ladata tallenteita Google Driveesi. Jos tallennetta ei voi ladata heti — olit offline-tilassa, sovellus sulkeutui, Drive nikotteli — se menee kertymään ja yritetään myöhemmin uudelleen. Järkevää.

Vika oli siinä, milloin "myöhemmin" tapahtui. Seuraavalla käynnistyksellä sovellus yritti tyhjentää koko kertymän kerralla. Yksi käyttäjä, jolla oli viikon verran odottavia tallenteita, muuttui samanaikaisten latauspyyntöjen ryöpyksi sillä hetkellä, kun hän avasi sovelluksen. Kerro tämä jokaisella käyttäjällä, joka käynnistää sovelluksen aamulla, ja taustajärjestelmältämme pyydettiin todentamaan, tarkistamaan nopeusrajat ja käsittelemään liikenneseinä samojen muutaman sekunnin sisällä — asiakkailta, jotka kaikki teknisesti käyttäytyivät oikein.

Taustajärjestelmämme teki oikean asian ja rajoitti tulvan nopeutta. Ja siinä alkoi toisen asteen vahinko. Nopeusrajoituksen vastaus on HTTP 429, ja 429 muistuttaa paljon muita vikoja, jos et ole varovainen:

  • Käynnistyksen profiilin haku sai 429:n, ja sovellus tulkitsi sen todennus epäonnistui -tapahtumaksi — kirjaten käyttäjät hetkeksi ulos täysin kelvollisesta istunnosta.
  • Transkriptioyhteys sai geneerisen 429:n ja näytti äänirajan täyttymisen päivityskehotteen — kertoen maksaville käyttäjille, että he olivat saavuttaneet kiintiön, jota he eivät olleet saavuttaneet.

Eli yksi juurisyy — tahdistamaton kertymä — tuotti kolme näkyvää oiretta: palvelinkuormituksen, väärät uloskirjautumiset ja väärät lisämyynnit. Klassinen itse-DoS:n muoto: kuormitus on pahasta, mutta se, minkä käyttäjät todella tuntevat, on kuormituksen oireiden väärintulkinta.

Korjaus, kahdessa kerroksessa

Pysäytä ryntäys. Latauskertymä on nyt tahdistettu — pyynnöt levitetään peräytymisellä, ja jäähtymisaika jokaisen 429:n jälkeen, jotta asiakas vetäytyy pois kuormittuneesta palvelimesta sen sijaan, että nojaisi siihen kovemmin. Thundering herdistä tulee siisti jono.

Pysäytä väärintulkinta. Ohimenevä 429 tai 5xx käynnistyksen aikana ei enää kirjaa sinua ulos — asiakas erottaa "palvelin on hetken kiireinen" ja "istuntosi on kelvoton" toisistaan. Ja geneerinen nopeusrajoituksen 429 transkriptioreitillä ei enää tekeydy äänikiintiövirheeksi; vain aito kiintiövastaus näyttää päivityskehotteen. Oppi, joka jäi mieleen: virhekoodi ei ole virheen merkitys. 429 tarkoittaa "hidasta", ei "sinut on kirjattu ulos" eikä "kiintiösi on lopussa" — ja asiakkaan on tiedettävä ero.

Elävyystikkaat, jotka seurasivat

Lauman tahdistaminen paljasti hiljaisemman ongelman: kun yhteys todella meni pieleen kuormituksen alla, kuinka nopeasti sen huomasimme? Hitaammin kuin halusimme. Joten v2.0.4 rakensi elävyystikkaat reaaliaikaista transkriptiota varten:

  • Sydämenlyönnit — transkriptiosokettia pingataan kiinteällä välillä, joten hiljaa kuollut yhteys havaitaan sekunneissa sen sijaan, että odotettaisiin seuraavan äänipätkän epäonnistumista.
  • Verkon-palautumisen uudelleenyhteyspotku — kun käyttöjärjestelmä ilmoittaa verkon palanneen, sovellus muodostaa yhteyden uudelleen ennakoivasti sen sijaan, että odottaisi kompastuvansa löytöön.
  • Ohjaus-ping/pong-elävyys — sovellustason edestakainen tarkistus, joka vahvistaa paitsi "soketti on auki", myös "toinen pää todella vastaa".
  • Palvelun omistama uudelleenyhteysportti — yksi paikka päättää, yhdistetäänkö uudelleen, sen sijaan että useat sovelluksen osat kilpailisivat siitä ja astuisivat toistensa varpaille.

Mikään tästä ei ole hohdokasta. Kaikki tämä on syy siihen, miksi v2-istunto tuntuu siltä, että se vain... pysyy yhdistettynä.

Se tapahtui taas tällä viikolla — yksi taso alempana

Tässä on osa, joka tekee tästä enemmän kuin sotatarinan. Sama vikaluokka nousi taas esiin päiviä sitten, yhden tason meidän alapuolellamme. Yksi asiakas laukaisi 21 transkriptioistunnon aloitusta alle 400 millisekunnissa — ja laukaisi puhepalveluntarjoajamme tilinlaajuisen 15 samanaikaisen pyynnön rajan. Ryntäys jaettua infrastruktuuria vastaan, aivan kuten latauskertymä, vain kohdistettuna riippuvuuteen eikä omaan taustajärjestelmäämme.

Muoto on identtinen, ja niin on korjauskin: ryntäävä asiakas tarvitsee single-flight-suojan, jottei se voi laukaista kahtakymmentä aloitusta yhtä aikomusta varten, ja jaettu resurssi tarvitsee käyttäjäkohtaisen katon, jottei yksi asiakas voi kuluttaa koko allasta. Olemme rakentaneet tästä asiakaspuolen version ennenkin — lataustahdistin on tämä malli. Nyt sovellamme sitä istunnon aloituksiin. Thundering herd ei ole vika, jonka korjaat kerran; se on muoto, jonka opit tunnistamaan kaikkialla, missä asiakkaat kohtaavat jaetun rajan.

Kolme asiaa mukaan otettavaksi

  1. Omat asiakkaasi ovat kuormitustesti, jota et ajoittanut. Kaikki, mikä nippuuntuu käynnistyksessä, yrittää uudelleen käynnistyksellä tai yhdistyy uudelleen herätessä, on thundering herd, joka odottaa riittävää käyttäjämäärää. Tahdista se ennen kuin heitä on.
  2. Erota koodi merkityksestä. 429 on väärimmin luettu tila, mitä on olemassa. "Hidasta" ei ole "kirjaudu ulos" eikä "maksa meille". Ohjaa jokainen vika sinne, mitä se todella tarkoittaa.
  3. Elävyys on tikkaat, ei lippu. "Onko yhteys elossa?" -kysymykseen on useita rehellisiä vastauksia eri kerroksissa — soketti auki, tavut virtaamassa, toinen pää vastaamassa, verkko läsnä. Vankka sovellus tarkistaa useamman kuin yhden.

Tämä on se hohdoton koneisto GeekBye v2:n tyyneyden alla. Luotettavuusominaisuuksista, jotka se mahdollisti, katso miksi AI-muistiinpanotyökalusi pysähtyy huonossa Wi-Fissä ja reaaliaikainen transkriptio, kun palomuuri estää WebSocketit (v2.0.8). Tämän sarjan naapurijulkaisuista miksi AI-muistiinpanotyökalusi lopettaa tallennuksen kesken kokouksen (v2.0.9).