Steven
Steven5 min lasīšana

Diena, kad mūsu lietotne DDoS-oja pati sevi

Neizsūtīto augšupielāžu uzkrājums, kas palaišanas brīdī tika izlaists viss uzreiz, pārvērta katru GeekBye klientu par nelielu pakalpojuma atteikuma (DoS) uzbrukumu mūsu pašu serveriem. Labojums — un savienojuma dzīvotspējas kāpnes, ko tas mūs piespieda uzbūvēt — ir viena no noderīgākajām lietām, ko mums iemācīja v2.

Uzticamība
Tīkli
Inženierija
GeekBye laidieni
Diena, kad mūsu lietotne DDoS-oja pati sevi

Katrs sadalīto sistēmu inženieris agri vai vēlu sastop "thundering herd" — dauzošo ganāmpulku: klientu masu, kas visi dara vienu un to pašu vienā mirklī, un koplietojamo resursu aiz tiem, kas ļodzās. Parasti tie ir kāda cita klienti. GeekBye v2.0.1 gadījumā tie bija mūsējie, un uzbrucējs bija mūsu pašu lietotne.

Kā piezīmju rīks uzbrūk pats sev

GeekBye var augšupielādēt ierakstus jūsu Google Drive. Ja ierakstu nevar augšupielādēt uzreiz — jūs bijāt bezsaistē, lietotne aizvērās, Drive iestreidzās — tas nonāk uzkrājumā, lai vēlāk mēģinātu vēlreiz. Saprātīgi.

Kļūme bija tajā, kad pienāca "vēlāk". Nākamajā palaišanas reizē lietotne mēģināja iztukšot visu uzkrājumu uzreiz. Viens lietotājs ar nedēļu neizsūtīto ierakstu kļuva par vienlaicīgu augšupielādes pieprasījumu izvirdumu tajā pašā mirklī, kad viņš atvēra lietotni. Sareiziniet ar katru lietotāju, kas palaiž lietotni no rīta, un mūsu aizmugursistēmai tika prasīts autentificēt, pārbaudīt ātruma ierobežojumus un apstrādāt trafika sienu tajās pašās dažās sekundēs — no klientiem, kas visi tehniski uzvedās pareizi.

Mūsu aizmugursistēma rīkojās pareizi un ierobežoja plūdu ātrumu. Un tur sākās otrās kārtas kaitējums. Ātruma ierobežojuma atbilde ir HTTP 429, un 429 ļoti līdzinās citām kļūmēm, ja neesat uzmanīgs:

  • Palaišanas profila iegūšana saņēma 429, un lietotne to uztvēra kā autentifikācija neizdevās — uz brīdi izrakstot lietotājus no pilnīgi derīgas sesijas.
  • Transkripcijas savienojums saņēma vispārīgu 429 un parādīja audio limita sasniegšanas jaunināšanas uzvedni — pastāstot maksājošiem lietotājiem, ka viņi ir sasnieguši kvotu, ko viņi nebija.

Tātad viens galvenais cēlonis — nesadalīts uzkrājums — radīja trīs redzamus simptomus: servera slodzi, viltus izrakstīšanos un viltus papildpārdošanu. Klasiskā pašizraisīta DoS forma: slodze ir slikta, bet tas, ko lietotāji patiešām jūt, ir slodzes simptomu nepareiza interpretācija.

Labojums, divos slāņos

Apturiet dauzīšanos. Augšupielāžu uzkrājums tagad ir sadalīts — pieprasījumi izkliedēti ar atkāpi, un atdzišanas periods pēc jebkura 429, lai klients atkāptos no pārslogota servera, nevis dauztu to vēl stiprāk. "Thundering herd" kļūst par kārtīgu rindu.

Apturiet nepareizu interpretāciju. Īslaicīgs 429 vai 5xx palaišanas laikā vairs jūs neizraksta — klients atšķir "serveris ir uz brīdi aizņemts" no "jūsu sesija ir nederīga". Un vispārīgs ātruma ierobežojuma 429 transkripcijas ceļā vairs neizliekas par audio kvotas kļūdu; tikai īsta kvotas atbilde parāda jaunināšanas uzvedni. Mācība, kas palika: kļūdas kods nav kļūdas nozīme. 429 nozīmē "palēnini", nevis "tu neesi autorizēts" un nevis "tev ir beigusies kvota" — un klientam ir jāzina atšķirība.

Dzīvotspējas kāpnes, kas sekoja

Ganāmpulka sadalīšana atklāja klusāku problēmu: kad savienojums slodzes laikā tiešām sabojājās, cik ātri mēs to pamanījām? Lēnāk, nekā mēs vēlējāmies. Tāpēc v2.0.4 izveidoja savienojuma dzīvotspējas kāpnes reāllaika transkripcijai:

  • Sirdspuksti — transkripcijas soketam tiek nosūtīts ping fiksētā intervālā, tāpēc klusi miris savienojums tiek atklāts sekundēs, nevis gaidot, kad neizdosies nākamais audio gabals.
  • Tīkla atjaunošanās atkārtotas savienošanās grūdiens — kad OS ziņo, ka tīkls ir atgriezies, lietotne proaktīvi atjauno savienojumu, nevis gaida, kad nejauši atklās to.
  • Vadības ping/pong dzīvotspēja — lietojumprogrammas līmeņa turp-atpakaļ pārbaude, kas apstiprina ne tikai "sokets ir atvērts", bet "otrs gals patiešām atbild".
  • Pakalpojumam piederoši atkārtotas savienošanās vārti — viena vieta izlemj, vai savienoties atkārtoti, nevis vairākas lietotnes daļas sacenšas to darīt un traucē cita citai.

Nekas no tā nav grezns. Viss tas ir iemesls, kāpēc v2 sesija jūtas tā, it kā tā vienkārši... paliktu savienota.

Tas notika atkal šonedēļ — vienu līmeni zemāk

Lūk daļa, kas padara šo par kaut ko vairāk nekā kara stāstu. Tā pati kļūmju klase atkal parādījās pirms dažām dienām, vienu līmeni zem mums. Viens klients palaida 21 transkripcijas sesijas sākumu mazāk nekā 400 milisekundēs — un pārsniedza mūsu runas nodrošinātāja konta mēroga ierobežojumu — 15 vienlaicīgi pieprasījumi. Dauzīšanās pret koplietojamu infrastruktūru, tieši tāpat kā augšupielāžu uzkrājums, tikai vērsta uz atkarību, nevis mūsu pašu aizmugursistēmu.

Forma ir identiska, un tāds pats ir arī labojums: dauzošajam klientam vajadzīgs single-flight aizsargs, lai tas nevarētu palaist divdesmit sākumu vienam nolūkam, un koplietojamajam resursam vajadzīgs ierobežojums uz lietotāju, lai viens klients nevarētu patērēt visu pūlu. Mēs esam uzbūvējuši klienta puses versiju šim jau iepriekš — augšupielāžu sadalītājs ir šis paraugs. Tagad mēs to pielietojam sesiju sākumiem. "Thundering herd" nav kļūda, ko izlabo vienreiz; tā ir forma, ko iemācies atpazīt visur, kur klienti sastop koplietojamu ierobežojumu.

Trīs lietas, ko paņemt līdzi

  1. Jūsu pašu klienti ir slodzes tests, ko jūs neplānojāt. Jebkas, kas grupē palaišanas laikā, atkārto mēģinājumus palaišanā vai savienojas atkārtoti pēc pamošanās, ir "thundering herd", kas gaida pietiekami daudz lietotāju. Sadaliet to, pirms jums to ir.
  2. Atšķiriet kodu no nozīmes. 429 ir visnepareizāk lasītais statuss, kāds vien pastāv. "Palēnini" nav "izraksties" un nav "samaksā mums". Novirziet katru kļūmi uz to, ko tā patiešām nozīmē.
  3. Dzīvotspēja ir kāpnes, nevis karogs. "Vai savienojums ir dzīvs?" ir vairākas godīgas atbildes dažādos slāņos — sokets atvērts, baiti plūst, otrs gals atbild, tīkls klāt. Izturīga lietotne pārbauda vairāk nekā vienu.

Šī ir tā negreznā mašinērija zem GeekBye v2 miera. Par uzticamības funkcijām, ko tā ļāva, lasiet kāpēc jūsu AI piezīmju rīks apstājas sliktā Wi-Fi un reāllaika transkripcija, kad ugunsmūris bloķē WebSockets (v2.0.8). Par kaimiņu laidieniem šajā sērijā — kāpēc jūsu AI piezīmju rīks pārtrauc ierakstīšanu sapulces vidū (v2.0.9).