Blog

Neúspěšné opětovné publikování nikdy nesmaže fungující backend

Dne 25. září smazalo neúspěšné opětovné publikování backend aplikace, který byl živý a fungoval zhruba dvě a půl hodiny. Kód, který vrací zpět nezdařené publikování, odstranil každou serverovou aplikaci, které se publikování dotklo, včetně těch, které už před jeho začátkem fungovaly. Teď se smazat smějí jen aplikace, které publikování vytvořilo. Aplikace, která už existovala, se vrátí přesně na verzi, kterou běžela před tím. Dvě navazující opravy ten samý den zajistily, že se vrácení provede i tehdy, když selže vlastní nástroj hostingové platformy pro nasazení, a že zdravá aplikace neselže jen proto, že spala.

Jak se backend publikuje

Pokud má vaše aplikace Mythex backend, tedy API nebo server, a ne jen statické soubory, publikování ho sestaví podle Dockerfile (receptu, jak aplikaci zabalit do image) a nasadí tento image na stroje naší hostingové platformy. Pak health check počká, až se nová verze skutečně spustí a zůstane běžet, a teprve potom se publikování označí jako živé.

Pokud cokoli na cestě selže, spustí se rollback, který to vrátí zpět. Správné provedení rollbacku je důležitější než téměř cokoli jiného v publikování, protože běží přesně ve chvíli, kdy se něco už pokazilo.

Problém 1: rollback smazal to, co měl obnovit

Rollback si držel seznam serverových aplikací, na které publikování nasadilo, a při selhání je všechny zničil. U prvního publikování je to správně: aplikace byla vytvořena před chvílí, nic na ní nezávisí a její smazání nechá věci tak, jak byly.

U opětovného publikování je to přesně špatně. Aplikace už existovala a obsluhovala skutečné návštěvníky. Dne 25. září smazalo neúspěšné opětovné publikování API aplikace, které bylo živé zhruba dvě a půl hodiny.

V témž kódu se skrýval i druhý způsob selhání. Pokud se smazání nepovedlo, rozbitý nový image zůstal na strojích, zatímco jsme majiteli tvrdili, že jeho aktuální web je stále živý. V okamžiku, kdy health check může selhat, je nový image už nasazen na všech strojích. Nedělat nic není totéž co vrátit zpět.

Oprava: smazat jen to, co jsme vytvořili, a zbytek obnovit

Každé publikování si teď u každé serverové aplikace, které se dotkne, zapíše:

  • zda ji toto publikování vytvořilo, a
  • pokud ne, jaký image běžela těsně předtím.

Při selhání dostane každá aplikace jedno ze tří zacházení:

  1. Vytvořilo ji toto publikování: smazat, jako dříve.
  2. Už existovala, předchozí image je známý: znovu nasadit předchozí image se stejnou konfigurací. Žádné sestavování, pohybuje se jen image zpět.
  3. Už existovala, předchozí image není znám: nechat být. Existující aplikace se nikdy nemaže, ani když ji nedokážeme obnovit.

Tato pravidla jsou malá čistá funkce s vlastními testy, takže se rozhodování nemůže vrátit k „smazat všechno“, aniž by test neprošel.

Problém 2: nástroj pro nasazení mohl selhat dřív, než jsme zapsali, jak vrátit zpět

Krátce po této opravě jsme v ní našli mezeru. Nástroj pro nasazení hostingové platformy spouští vlastní smoke testy: pokud se nové stroje shodí, skončí chybou. Stane se to ale až poté, co je nový image už na strojích.

Náš kód zaregistroval aplikaci k rollbacku až ve chvíli, kdy nástroj vrátil úspěch. Pokud nástroj samotný nasazení shodil, aplikace na seznamu k rollbacku ještě nebyla, takže se nic neobnovilo. Na naší staging verzi nechalo rozbité publikování běžet rozbitý image.

Oprava: zaregistrovat vrácení dřív, než začneme

Aplikace se teď k rollbacku registruje – včetně toho, zda byla vytvořena a jaký image běžela – hned jak je připravena a dřív, než se na ni cokoli nasadí. Ať selže cokoli dál, rollback ví, co má vrátit. Ověřili jsme to lokálně: rozbité opětovné publikování selhalo v smoke testech nástroje pro nasazení a předchozí verze dál odpovídala.

Problém 3: spící aplikace byla označena jako „nikdy nespuštěná“

Publikované aplikace na Mythexu při nečinnosti usínají, aby šetřily vaše kredity. Opětovné publikování nechá spící stroj zastavený, takže health check ho musí probudit. Požádal platformu, aby stroj spustila jednou, a odpověď ignoroval.

Dne 25. září tento jediný požadavek na spuštění nikam nedorazil. Zdravé API zůstalo zastavené po celých pět minut health checku a bylo označeno jako selhání s hláškou „1 stroj se nikdy nespustil (poslední stav: zastaveno)“.

Platforma občas spuštění odmítne. Při reprodukci tohoto chování vrátila konflikt „lease currently held“ i bez toho, aby ho někdo vyvolal, a spuštění odmítá, dokud se stroj aktualizuje.

Oprava: ptát se znovu a zaklepat na dveře

Health check teď:

  • žádá o spuštění zastaveného stroje každých 20 sekund, dokud čeká,
  • zapisuje, co platforma odpověděla, když spuštění odmítla, a
  • pošle aplikaci jeden obyčejný požadavek, jako by ho poslal návštěvník. Proxy platformy probudí spící stroj, jakmile požadavek dorazí.

Na skutečné platformě jsme to reprodukovali s jednorázovou aplikací, jejíž první spuštění bylo odmítnuto. Před opravou publikování selhalo po 91 sekundách. Po opravě se publikovalo za 20 sekund. Aplikace, která se opravdu hroutí při startu, pořád selže, jak má.

Co si z toho bereme

  • Rollback musí rozlišovat nové a existující. „Vrátit zpět“ u něčeho, co jsme vytvořili, znamená smazat. „Vrátit zpět“ u něčeho, co tu už bylo, znamená obnovit. Když je oboje zacházeno stejně, bezpečnostní mechanismus smaže fungující aplikaci.
  • Zapište si, jak vrátit zpět, dřív, než začnete jednat. Pokud se vrácení zaznamená až poté, co krok uspěje, krok, který selže v půlce, nezanechá nic, čím by se dalo vrátit.
  • Nikdy neignorujte odpověď na požadavek, na kterém závisíte. Jedno ignorované „ne“ proměnilo zdravou aplikaci v neúspěšné publikování.

Související oprava ze stejného dne: odchytávání aplikací, které se hroutí hned po publikování. O tom, co se stane, když publikování selže na vaší straně, najdete v dokumentaci v části řešení problémů s publikováním.

Mythex · Pricing · Vytvořte cokoli s AI · Šablony webů a aplikací · Mythex v porovnání · Slovník tvorby aplikací s AI · Bezplatné nástroje pro tvorbu aplikací s AI · English

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