Blog

Hogyan jutottunk nulla 502-es hibához a deployoknál

A Mythex backendjének minden deployjánál néhány kérés 502 Bad Gateway hibával meghiúsult. Nem sok — de egy 502 deploy közben azt jelenti, hogy valakinek a kattintása semmit nem csinált, vagy egy build, amelyet figyelt, egy pillanatra megakadt. Két külön problémára vezettük vissza: egy önjavító watchdogra, amely a deployjainkkal versengett, és egy résre aközött, amikor egy szerver már nem hallgatózik, és amikor a terheléselosztó már nem küld neki forgalmat. Az egymás utáni három éles deploy a javítások után 10-ről 6-ra, majd 0-ra csökkent.

A felállás

Az API-nk és az orchestratorunk konténerekként fut egy kis szerver-csoporton, egy AWS Application Load Balancer (ALB) mögött. Egy deploy egyszerre egy szervert frissít: leüríti a régi konténereket, elindítja az újakat, és továbblép. Minden szerveren egy watchdog ellenőrzi, hogy a konténerek futnak-e, és újraindít minden leállt konténert — azért van, hogy egy hajnali 3-kor összeomló folyamat újra működjön anélkül, hogy valakit fel kellene ébreszteni.

Mindkettő önmagában ésszerű. Együtt nem voltak azok.

1. probléma: a watchdog versenyzett a deployjal

A watchdog percenként futott, és egyetlen sikertelen egészségügyi ellenőrzésre „gyógyított”. Egy deploy szándékosan legfeljebb 150 másodpercig üríti a szolgáltatásokat — ezalatt az egészségügyi ellenőrzésnek kellene bukni. Így a watchdog minden egyes deploy alatt tüzelt.

Az idők többségében ártalmatlanul vesztette el a versenyt. Egyszer nyert: átírta a compose-fájlt (a leírást arról, mely konténereknek kell futniuk) egy deploy közepén, és egy szervert gateway-konténer nélkül hagyott — miközben a deploy-feladat sikeresnek jelentette magát.

A javítások:

  • Egy zár. A deploy most ugyanazt a fájlzárat veszi, mint a szerver bootstrap-szkriptje, így a watchdog és a deploy soha nem futhat egyszerre.
  • Négy ütem, nem egy. A watchdognak négy egymást követő sikertelen ellenőrzés kell, mielőtt cselekszik. Egy leürülő szolgáltatás már nem tűnik halottnak.
  • Egy definíció. A compose-fájlnak most egyetlen forrása van, amelyet a szerverekre publikálunk, nem olyan másolatok, amelyek eltérhetnek.
  • Ellenőrizd, ne bízz. A deploy-feladat már nem azért sikeres, mert egy parancs visszatért. Minden szerver API-ját, orchestratorát, gateway-jét és publikáló munkását ellenőrzi, mielőtt sikeres lehetne.

2. probléma: a szerver előbb ment el, mint a forgalom

A második probléma csendesebb volt. Amikor egy deploy leüríti a szervert, az 503-mal válaszol az egészségügyi végpontjára, hogy a terheléselosztó kivegye a forgalomból. A miénk ezt 5 másodpercig tette, aztán leállt.

De az ALB csak időnként ellenőrzött, és egymás utáni több sikertelen ellenőrzés kellett ahhoz, hogy egy célpontra ne küldjön többet forgalmat — egészben nagyjából 60 másodperc. Így körülbelül 55 másodpercig a terheléselosztó olyan szervernek küldte az igazi kéréseket, amely már nem hallgatózott. Ezek voltak a mi 502-eseink.

A javítás az volt, hogy a két idővonal összhangba került:

  • A célcsoport most 5 másodpercenként ellenőriz, és 2 sikertelen ellenőrzés után jelöli egy célpontot egészségtelennek — nagyjából 10 másodperc alatt észreveszi.
  • A leürítés még 15 másodpercig szolgálja ki az igazi forgalmat, miután elkezdett sikertelen egészségügyi ellenőrzéseket adni, így mindig van átfedés.
  • Ezek a beállítások az infrastruktúrát létrehozó szkriptben élnek, nem egy konzolban, amelyet valaki egyszer kattintgatott.

A számokat egymáshoz kötni

Az ilyen időtúllépések egymástól függnek. A leürítésnek tovább kell tartania, mint amennyi idő alatt a terheléselosztó észreveszi a változást; a leürítésnek és a leállásnak be kell fejeződnie, mielőtt a konténert kényszerítetten leállítják. Könnyű, hogy valaki hat hónap múlva megváltoztat egy számot, és csendben visszahozza a hibát.

Ezért ezeket a kapcsolatokat tesztekként rögzítettük: a leürítésnek hosszabbnak kell lennie, mint az egészségügyi ellenőrzés intervallumának és a sikertelenségi küszöbnek a szorzata; az újbóli egészségessé váláshoz szükséges idő rövid marad; az egész leürítésnek bele kell férnie a konténer leállási türelmi idejébe. Ha egy számot a többi nélkül változtatsz meg, a CI elbukik. A teszteket magukat is mutációteszteltük: minden számot rossz értékre állítottunk, és ellenőriztük, hogy egy teszt elkapja-e.

A deploy mérése könnyen elrontható

A kezdeti mérésünk szerint egy tiszta deploy körülbelül 3%-ban hibás volt. Nem volt az. Minden nem-200-as választ számoltunk, és egy 503 az egészségügyi végpontról leürítés közben nem hiba — a leürítés teszi a dolgát, jelzi a terheléselosztónak, hogy ne válassza ki azt a szervert, miközben az még szolgálja ki az igazi kéréseket.

Amit a felhasználók éreznek, az a 502: a kérés semmit nem ért el. Csak ezeket számolva kaptunk valós képet — 10, majd 6, majd 0 három éles deployon keresztül.

Amit ebből tanultunk

  • Az önjavításnak tudnia kell a tervezett leállásokról. Egy watchdog, amely nem tudja megkülönböztetni a deployt az összeomlástól, előbb-utóbb a deployjal fog versenyezni.
  • A leürítés kézfogás. A szervernek addig kell szolgálnia, amíg a terheléselosztó bizonyíthatóan nem küld neki több forgalmat, és ezt az időzítést a terheléselosztón kell beállítani, nem a szerveren.
  • A változatlan feltételeket tesztekbe kódold. Az üzemeltetési számok eltérnek. Azok a tesztek, amelyek egymáshoz kötik őket, nem.
  • Döntsd el, mit mérsz, mielőtt mérsz. Az „hibák” rossz mérőszám volt; a „kérések, amelyek semmit nem értek el” volt a helyes.

Ha a Mythexen publikálsz appot, ebből semmi nem látszik neked — ez a lényeg. Kapcsolódó: hogyan marad elérhető a publikált appod az újrapublikálás közben.

Mythex · Pricing · Építs bármit AI-val · Weboldal- és alkalmazássablonok · A Mythex összehasonlítva · AI-alapú alkalmazásépítési szószedet · Ingyenes eszközök AI-alapú alkalmazásépítéshez · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Հայերեն 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 简体中文 繁體中文(香港) 繁體中文(台灣)