Kako smo spravili napake 502 pri objavah na nič
Vsakič, ko smo objavili backend Mythexa, je nekaj zahtevkov vrnilo 502 Bad Gateway. Ne veliko, a napaka 502 med objavo pomeni, da je klik nekoga ničesar ni naredil ali da se je gradnja, ki jo je spremljal, za trenutek ustavila. Vzrok smo izsledili v dveh ločenih težavah: samozdravilni watchdog, ki se je boril z objavami, in vrzel med trenutkom, ko strežnik preneha poslušati, in trenutkom, ko load balancer preneha pošiljati nanj promet. Pri treh zaporednih produkcijskih objavah po popravkih je število padlo z 10 na 6 in nato na 0.
Postavitev
Naš API in orkestrator tečeta kot vsebniki na majhni skupini strežnikov za AWS Application Load Balancerjem (ALB). Objava posodobi en strežnik naenkrat: izprazni stare vsebnike, zažene nove in gre naprej. Watchdog na vsakem strežniku preverja, ali so vsebniki živi, in ponovno zažene vsakega, ki ni — obstaja zato, da se strojno zrušen proces ob 3. uri zjutraj vrne, ne da bi kdo moral vstati.
Oboje je samo po sebi razumno. Skupaj pa nista delovala.
Težava 1: watchdog je tekmoval z objavo
Watchdog je tekel enkrat na minuto in je ozdravil po enem neuspelem preverjanju. Objava namerno izprazni storitve do 150 sekund — med tem preverjanje stanja mora neuspeti. Watchdog se je tako sprožil med vsako objavo.
Večinoma je tekmo izgubil brez škode. Enkrat je zmagal: prepisal je datoteko compose (opis, kateri vsebniki naj tečejo) sredi objave in pustil strežnik brez prehodnega vsebnika — medtem ko je opravilo objave poročalo o uspehu.
Popravki:
- Ena ključavnica. Objava zdaj uporablja isto datotečno ključavnico kot bootstrap skripta strežnika, zato watchdog in objava nikoli ne tečeta hkrati.
- Štirje zaporedni neuspehi, ne eden. Watchdog potrebuje štiri zaporedne neuspele preveritve, preden ukrepa. Izpraznjena storitev ne izgleda več mrtva.
- Ena definicija. Datoteka compose ima zdaj en sam vir, objavljen na strežnike, namesto kopij, ki bi se lahko razšle.
- Preveri, ne zaupaj. Opravilo objave ne uspe več zato, ker je ukaz vrnil izhod. Pred uspehom preveri API, orkestrator, prehod in objavnega delavca na vsakem strežniku.
Težava 2: strežnik je odšel prej kot promet
Druga težava je bila tišja. Ko objava izprazni strežnik, strežnik na svoji zdravstveni končni točki 5 sekund vrača 503, da ga load balancer odstrani iz prometa, nato se ugasne.
Toda ALB preverja zdravje le občasno in za odstranitev cilja potrebuje več zaporednih neuspelih preverjanj — od začetka do konca približno 60 sekund. Tako je load balancer približno 55 sekund še vedno pošiljal prave zahtevke strežniku, ki je že nehal poslušati. To so bile naše napake 502.
Popravek je bil uskladiti obe časovnici:
- Ciljna skupina zdaj preverja vsakih 5 sekund in cilj označi za nezdravega po 2 neuspelih preverjanjih — približno 10 sekund do zaznave.
- Izpraznitev še 15 sekund streže prave zahtevke, potem ko začne neuspešno odgovarjati na preverjanja, tako da je vedno prekrivanje.
- Te nastavitve so v skripti, ki pripravlja infrastrukturo, ne v konzoli, ki jo je nekdo enkrat kliknil.
Da številke držijo skupaj
Te časovne omejitve so odvisne druga od druge. Izpraznitev mora trajati dlje, kot balanser potrebuje, da opazi; izpraznitev in zaustavitev skupaj morata končati, preden se vsebnik prisilno ubije. Lahko se zgodi, da nekdo čez šest mesecev spremeni eno številko in tiho znova uvede napako.
Zato smo ta razmerja zapisali kot teste: izpraznitev mora biti daljša od intervala preverjanja, pomnoženega s pragom neuspeha; čas do ponovne oznake kot zdrav mora ostati kratek; celotna izpraznitev se mora prilegati znotraj časa milosti vsebnika za zaustavitev. Spremenite eno številko brez drugih in CI pade. Testirali smo tudi same teste: vsako številko smo spremenili v napačno vrednost in preverili, ali jo test ujame.
Merjenje objave je lahko zavajajoče
Naša prva meritev je trdila, da je čista objava pokvarjena za približno 3 %. Ni bila. Šteli smo vsak odgovor, ki ni 200, odgovor 503 z zdravstvene končne točke med izpraznitvijo pa ni napaka — to je izpraznitev, ki opravlja svoje delo: sporoča balanserju, naj med tem ne izbere tega strežnika, medtem ko še vedno streže prave zahtevke.
Uporabnik občuti napako 502: zahtevek ni dosegel ničesar. Ko smo šteli samo te, je bila slika pravilna — 10, nato 6, nato 0 pri treh produkcijskih objavah.
Kaj smo iz tega izvlekli
- Samozdravljenje mora vedeti za načrtovane izpade. Watchdog, ki ne more ločiti objave od zrušitve, se bo sčasoma boril z objavo.
- Izpraznitev je rokovanje. Strežnik mora streči, dokler balanser ne dokaže, da je nehal pošiljati promet, ta čas pa je nastavljen na balanserju, ne na strežniku.
- Invariante zapišite kot teste. Operativne številke se sčasoma razhajajo. Testi, ki jih povežejo med seboj, ne.
- Odločite, kaj merite, preden merite. »Napake« so bile napačna metrika; »zahtevki, ki niso dosegli ničesar« je bila prava.
Če objavite aplikacijo na Mythexu, vam ničesar od tega ni vidno — in prav v tem je bistvo. Sorodno: kako vaša objavljena aplikacija ostane dosegljiva med ponovno objavo.