Բռնել հավելվածները, որոնք խափանվում են հրապարակումից անմիջապես հետո
Սեպտեմբերի 25-ին երեք հրապարակում համարվեցին հաջողված, թեև հավելվածի API-ն խափանվում էր գործարկման յուրաքանչյուր վայրկյանին։ Քանի որ դրանք «հաջողվեցին», rollback չգործարկվեց. մի քանի րոպե անց ֆոնային ստուգումը դրանք ձախողեց, և ամբողջ կայքը ցույց տվեց 404։ Health check-ը խափանումները հաշվում էր հարթակի իրադարձությունների ցուցակում, որը յուրաքանչյուր մեքենայի համար պահում է միայն վերջին հինգ իրադարձությունը, ուստի խափանումների ցիկլը լցնում է այն, և հաշիվը երբեք չի աճում։ Այժմ այն համեմատում է ամենավերջին խափանման ժամանակը, և խափանվող ցիկլով հրապարակումը ձախողվում է և վերականգնում նախորդ տարբերակը։
Ինչի համար է սպասում հրապարակումը
Երբ Mythex-ում հրապարակում ես backend ունեցող հավելված, նոր տարբերակը տեղադրվում է մեր հոսթինգ հարթակի մեքենաների վրա, և health check-ը որոշում է, թե հրապարակումը ակտիվ է դարձել, թե ձախողվել։ Եթե ձախողվել է, rollback-ը վերադարձնում է նախորդ տարբերակը։
Դժվար մասն այն է, որ «սկսված» և «սպասարկում» նույնը չեն։ Հարթակը մեքենան սկսված է համարում, երբ այն բարձրանում է։ Հավելված, որը խափանվում է գործարկման մեկ վայրկյան անց, անմիջապես վերագործարկվում է, և մի պահ անց ընթերցվում է որպես կրկին սկսված։ Ուստի health check-ը ժամանակի ընթացքում մի քանի շերտ է ստացել.
- Նայիր երկու անգամ։ Երբ մեքենան ընթերցվում է որպես սկսված, կարճ սպասիր և նորից նայիր։ Գործարկման ժամանակ խափանումը հաճախ ձախողում է երկրորդ նայվածքը։
- Հետևիր խափանման ցիկլերին։ Եթե հարթակը հայտնում է, որ մեքենան շարունակաբար խափանվել է, և այն դադարեցրել է վերագործարկումը, ձախողիր։
- Հաշվիր խափանումները հրապարակման սկզբից ի վեր։ Երկու «սկսված» նայվածքները կարող են ընդգրկել մեկ վերագործարկում։ Ուստի եթե այս հրապարակման սկզբից ի վեր եղել է որևէ խափանում, նայիր երրորդ անգամ. եթե խափանումները ավելի շատ են, քան նախորդ նայվածքում, հավելվածը չի մնում վեր։
Երրորդ ստուգումն է, որ այստեղ ձախողվեց։
Ինչու հաշիվը մնաց հաստատուն
Խափանման տեղեկությունը գալիս է յուրաքանչյուր մեքենայի իրադարձությունների ցուցակից. մեկնարկներ, դուրսգրումներ, վերագործարկումներ։ Հարթակը մեքենայի համար պահում է միայն վերջին հինգ իրադարձությունը։
Պատկերացրու հավելված, որը խափանվում է յուրաքանչյուր գործարկման 2,5 վայրկյանի ընթացքում, ինչպես դրանցից մեկը։ Յուրաքանչյուր ցիկլ ավելացնում է մեկ խափանում և մեկ մեկնարկ։ Մի քանի ցիկլից հետո ցուցակը լցված է։ Այնուհետև յուրաքանչյուր նոր իրադարձություն դուրս է մղում մեկ հին։ Ցուցակը սահում է առաջ, բայց միշտ պահում է մոտավորապես նույն խառնուրդը. մի քանի խափանում, մի քանի մեկնարկ։
Ուստի «քանի խափանում է եղել հրապարակման սկզբից ի վեր» հարցը յուրաքանչյուր նայվածքում վերադարձնում էր նույն թիվը։ Երկրորդ նայվածքը տեսավ, ասենք, երկու խափանում։ Երրորդ նայվածքը նույնպես տեսավ երկու. տարբեր խափանումներ, բայց նույն թիվը։ Ստուգումը եզրակացրեց, որ խափանումները դադարել են, և հրապարակումն անցավ։
Սա կրկնվեց երեք անգամ սեպտեմբերի 25-ին, երկու հավելվածի վրա։ Յուրաքանչյուր անգամ.
- հրապարակումը նշվեց որպես ակտիվ,
- rollback չգործարկվեց, որովհետև ոչինչ չէր ձախողվել,
- մեր reconciler-ը, ֆոնային աշխատանք, որը հետագայում ստուգում է deployment-ները, մի քանի րոպե անց ձախողեց deployment-ը,
- և ամբողջ կայքը վերադարձրեց 404։
Հրապարակում, որը ժամանակին է ձախողվում, վերականգնելի է. rollback-ը վերականգնում է նախորդ տարբերակը։ Հրապարակում, որը ձախողվում է մի քանի րոպե ուշ, հաջողություն հայտարարվելուց հետո, արդեն բաց է թողել իր rollback-ը։
Ինչպես գտանք այն
Վերարտադրեցինք լոկալ. վերցրինք աշխատող API, թողեցինք, որ քնի, ապա նորից հրապարակեցինք փոփոխությամբ, որը խափանվում էր գործարկման ժամանակ։ Health check-ը նշեց այն որպես ակտիվ։
Սա համընկավ արտադրության հետ. երեք հրապարակումներից յուրաքանչյուրում հավելվածը մահանում էր յուրաքանչյուր գործարկման մի քանի վայրկյան անց, բայց խափանումների հաշիվը, որը ստուգումը համեմատում էր, երբեք չէր աճում նայվածքների միջև։
Շտկումը. համեմատիր ամենավերջին խափանումը, ոչ թե հաշիվը
Խափանումները հաշվելու փոխարեն ստուգումն այժմ նայում է ամենավերջին խափանման ժամանակին հրապարակման սկզբից ի վեր։
Եթե երկրորդ նայվածքը ցույց է տալիս որևէ խափանում հրապարակման սկզբից հետո, ստուգումը սպասում է և նայում է երրորդ անգամ։ Եթե երրորդ նայվածքի ամենավերջին խափանումը ավելի ուշ է, քան երկրորդի ամենավերջինը, մեքենան նորից խափանվել է միջանկյալում։ Այն չի մնում վեր, և հրապարակումը ձախողվում է՝ հաղորդագրությամբ, որ մեքենան հրապարակումից ի վեր բազմիցս խափանվել է և դեռ վերագործարկվում է։
Սա աշխատում է անկախ նրանից, թե որքան կարճ է իրադարձությունների ցուցակը. հինգ իրադարձության սահող պատուհանը կարող է թաքցնել, թե քանի խափանում է եղել, բայց չի կարող թաքցնել, որ նորը նոր է տեղի ունեցել. ամենավերջին իրադարձությունն է միշտ պահվում։
Այս փոփոխությամբ լոկալ վերարտադրումը ճիշտ է վարվում. հրապարակումը ձախողվում է, և նախորդ image-ը վերականգնվում է։ Կա նաև թեստ, որը մոդելավորում է հարթակի վարքը. յուրաքանչյուր նայվածք ավելացնում է խափանում և մեկնարկ և կրճատում ցուցակը մինչև հինգ, և ստուգում է, որ վճիռը ձախողում է, ոչ թե անցում։
Ինչ ենք սա սովորել
- Իմացիր քո հաշվելու տվյալների ձևը. Սահմանափակ ցուցակի վրա հաշվելը այլևս ոչինչ չի նշանակում, երբ ցուցակը լցված է։ Սահմանափակումը թաքնված չէր. պարզապես ստուգումը չէինք նախագծել դրա շուրջ։
- Նախընտրիր «տեղի ունեցավ արդյո՞ք նորություն» հարցը «քանի՞ բան տեղի ունեցավ» հարցից։ Ամենավերջին ժամանակի դրոշմը գոյատևում է կրճատմանը. գումարը՝ ոչ։
- Ուշ ձախողումը ավելի վատ է, քան վաղ ձախողումը։ Նույն կոտրված build-ը անվնաս է, եթե հրապարակումը ձախողվում է և հետ է շրջվում, և կայքը վայր է ընկնում, եթե այն նախ հայտարարվում է հաջողված։
- Վերարտադրիր իրական պայմաններում. Սխալը պահանջում էր մեքենա, որը արդեն բավականաչափ անգամ էր խափանվել, որ լցնի իր իրադարձությունների ցուցակը։ Թեստում մեկ արագ խափանումը այն չէր ցույց տա։
Այս շտկումը զուգորդվում է նույն օրվա մեկ այլ շտկման հետ, որը համոզվեց, որ rollback-ը վերադարձնում է հին տարբերակը, այլ ոչ թե ջնջում այն. ձախողված վերահրապարակումը երբեք չի ջնջում աշխատող backend-ը։ Եթե քո հավելվածը չի հրապարակվում, քանի որ խափանվում է մեկնարկի ժամանակ, հրապարակման խնդիրների լուծման փաստաթղթերը և մեր ուղեցույցը AI-ով կառուցված հավելվածի սխալների որոնման լավ տեղեր են սկսելու համար։