![Search icon](https://hackernoon.imgix.net/search-new.png?w=19&h=19)
Programinės įrangos atsparumas reiškia programos gebėjimą toliau sklandžiai ir patikimai veikti net iškilus netikėtoms problemoms ar gedimams. Fintech projektuose atsparumas yra ypač svarbus dėl kelių priežasčių. Pirma, įmonės privalo laikytis reguliavimo reikalavimų, o finansų reguliavimo institucijos pabrėžia veiklos atsparumą, kad išlaikytų sistemos stabilumą. Be to, dėl skaitmeninių įrankių paplitimo ir priklausomybės nuo trečiųjų šalių paslaugų teikėjų „Fintech“ įmonėms kyla didesnė grėsmė saugumui. Atsparumas taip pat padeda sumažinti gedimų, kuriuos sukelia įvairūs veiksniai, pvz., kibernetinės grėsmės, pandemijos ar geopolitiniai įvykiai, riziką, taip apsaugodamas pagrindines verslo operacijas ir svarbiausią turtą.
Atsparumo modeliais suprantame geriausios praktikos ir strategijų rinkinį, skirtą užtikrinti, kad programinė įranga galėtų atlaikyti trikdžius ir išlaikyti savo veiklą. Šie modeliai veikia kaip saugos tinklai, suteikdami mechanizmus, leidžiančius valdyti klaidas, valdyti apkrovą ir atsigauti po gedimų, taip užtikrinant, kad programos išliktų tvirtos ir patikimos nepalankiomis sąlygomis.
Dažniausiai naudojamos atsparumo strategijos apima pertvarą, talpyklą, atsarginę atmintį, pakartotinį bandymą ir grandinės pertraukiklį. Šiame straipsnyje aptarsiu juos išsamiau ir pateiksiu problemų, kurias jie gali padėti išspręsti, pavyzdžiais.
Pažvelkime į aukščiau pateiktą nustatymą. Turime labai įprastą programą su keliomis užpakalinėmis sistemomis, iš kurių galime gauti duomenų. Prie šių užpakalinių sistemų yra prijungti keli HTTP klientai. Pasirodo, kad visi jie turi tą patį ryšio baseiną! Taip pat kiti ištekliai, pvz., CPU ir RAM.
Kas atsitiks, jei vienai iš užpakalinių sistemų kils kokių nors problemų, dėl kurių užklausos delsa bus didelė? Dėl ilgo atsako laiko visas ryšio telkinys bus visiškai užimtas užklausų, laukiančių atsakymų iš backend1. Todėl užklausos, skirtos sveikiems backend2 ir backend3, negalės tęsti, nes baseinas išnaudotas. Tai reiškia, kad gedimas vienoje iš mūsų galinių programų gali sukelti visos programos gedimą. Idealiu atveju norime, kad pablogėtų tik funkcionalumas, susijęs su gedimu, o likusi programos dalis ir toliau veiktų įprastai.
Kas yra pertvaros modelis?
Terminas „Pertvaros raštas“ kilęs iš laivų statybos ir apima kelių izoliuotų laivo skyrių sukūrimą. Jei viename skyriuje atsiranda nuotėkis, jis prisipildo vandens, bet kiti skyriai lieka nepakitę. Ši izoliacija neleidžia visam laivui nuskęsti dėl vieno pažeidimo.
Pertvaros šabloną galima naudoti norint atskirti įvairių tipų išteklius programoje, kad vienos dalies gedimas nepaveiktų visos sistemos. Štai kaip galime tai pritaikyti mūsų problemai:
Tarkime, kad mūsų užpakalinės sistemos turi mažą tikimybę susidurti su klaidomis atskirai. Tačiau kai operacija apima užklausą visų šių galinių programų lygiagrečiai, kiekviena gali savarankiškai grąžinti klaidą. Kadangi šios klaidos atsiranda nepriklausomai, bendra klaidos tikimybė mūsų programoje yra didesnė nei bet kurios atskiros programos klaidos tikimybė. Kaupiamąją klaidos tikimybę galima apskaičiuoti naudojant formulę P_total=1−(1−p)^n, kur n yra užpakalinių sistemų skaičius.
Pavyzdžiui, jei turime dešimt užpakalinių programų, kurių kiekvienos klaidos tikimybė yra p=0,001 (atitinka 99,9 %) SLA, gauta klaidų tikimybė yra tokia:
P_viso = 1−(1−0,001)^10 = 0,009955
Tai reiškia, kad mūsų bendras SLA sumažėja iki maždaug 99 %, o tai rodo, kaip sumažėja bendras patikimumas, kai lygiagrečiai pateikiami užklausos keliuose foniniuose įrenginiuose. Norėdami sumažinti šią problemą, galime įdiegti talpyklą atmintyje.
Atmintyje esanti talpykla tarnauja kaip didelės spartos duomenų buferis, kuriame saugomi dažnai pasiekiami duomenys ir nereikia kiekvieną kartą gauti jų iš galimai lėtų šaltinių. Kadangi talpyklos, saugomos atmintyje, turi 0 % klaidų tikimybę, palyginti su duomenų gavimu tinkle, jos žymiai padidina mūsų programos patikimumą. Be to, talpyklos kaupimas sumažina tinklo srautą ir dar labiau sumažina klaidų tikimybę. Vadinasi, naudodami talpyklą atmintyje, galime pasiekti dar mažesnį klaidų lygį savo programoje, palyginti su mūsų užpakalinėmis sistemomis. Be to, talpyklos atmintyje siūlo greitesnį duomenų gavimą nei gavimas tinkle, taip sumažindamos programos delsą – tai yra pastebimas pranašumas.
Naudojant suasmenintus duomenis, pvz., vartotojų profilius ar rekomendacijas, talpyklos naudojimas atmintyje taip pat gali būti labai efektyvus. Tačiau turime užtikrinti, kad visos vartotojo užklausos būtų nuosekliai nukreipiamos į tą patį programos egzempliorių, kad būtų panaudoti jų talpykloje saugomi duomenys, o tam reikia fiksuotų seansų. Priklijuotų seansų įgyvendinimas gali būti sudėtingas, tačiau šiam scenarijui mums nereikia sudėtingų mechanizmų. Nedidelis srauto perbalansavimas yra priimtinas, todėl užteks stabilaus apkrovos balansavimo algoritmo, pavyzdžiui, nuoseklaus maišos.
Be to, mazgo gedimo atveju nuosekli maiša užtikrina, kad tik su sugedusiu mazgu susieti vartotojai bus perbalansuojami, taip sumažinant sistemos sutrikimus. Šis metodas supaprastina personalizuotų talpyklų valdymą ir padidina bendrą mūsų programos stabilumą ir našumą.
Jei duomenys, kuriuos ketiname saugoti talpykloje, yra labai svarbūs ir naudojami kiekvienoje mūsų sistemos apdorojamoje užklausoje, pvz., prieigos politikoje, prenumeratos planuose ar kituose mūsų domeno gyvybiškai svarbiuose objektuose, šių duomenų šaltinis gali reikšti didelę mūsų sistemos gedimo vietą. Norint išspręsti šį iššūkį, vienas iš būdų yra visiškai pakartoti šiuos duomenis tiesiai į mūsų programos atmintį.
Pagal šį scenarijų, jei duomenų kiekį šaltinyje galima valdyti, galime pradėti procesą atsisiųsdami šių duomenų momentinę kopiją mūsų programos pradžioje. Vėliau galime gauti atnaujinimų įvykius, siekdami užtikrinti, kad talpykloje esantys duomenys būtų sinchronizuoti su šaltiniu. Taikydami šį metodą padidiname prieigos prie šių svarbių duomenų patikimumą, nes kiekvienas nuskaitymas vyksta tiesiai iš atminties su 0% klaidos tikimybe. Be to, duomenų gavimas iš atminties yra ypač greitas, todėl mūsų programos našumas optimizuojamas. Ši strategija veiksmingai sumažina riziką, susijusią su pasitikėjimu išoriniu duomenų šaltiniu, užtikrindama nuoseklią ir patikimą prieigą prie svarbios informacijos, reikalingos mūsų taikomosios programos veikimui.
Tačiau būtinybė atsisiųsti duomenis apie programos paleidimą ir taip vilkinti paleidimo procesą pažeidžia vieną iš „12 faktorių programos“ principų, skatinančių greitą programos paleidimą. Tačiau nenorime prarasti talpyklos naudojimo pranašumų. Norėdami išspręsti šią dilemą, panagrinėkime galimus sprendimus.
Greitas paleidimas yra labai svarbus, ypač tokioms platformoms kaip Kubernetes, kurios priklauso nuo greito programų perkėlimo į skirtingus fizinius mazgus. Laimei, „Kubernetes“ gali valdyti lėtai paleidžiamas programas naudodama tokias funkcijas kaip paleisties zondai.
Kitas iššūkis, su kuriuo galime susidurti, yra konfigūracijų atnaujinimas, kai programa veikia. Dažnai norint išspręsti gamybos problemas, reikia koreguoti talpyklos laiką arba užklausos skirtąjį laiką. Net jei galime greitai įdiegti atnaujintus konfigūracijos failus savo programoje, norint pritaikyti šiuos pakeitimus, paprastai reikia paleisti iš naujo. Prailginus kiekvienos programos paleidimo laiką, nuolatinis paleidimas iš naujo gali žymiai atidėti pataisų diegimą mūsų vartotojams.
Norėdami tai išspręsti, vienas iš sprendimų yra konfigūracijas saugoti lygiagrečiame kintamajame ir periodiškai jį atnaujinti fono gijoje. Tačiau dėl tam tikrų parametrų, pvz., HTTP užklausos skirtojo laiko, gali reikėti iš naujo inicijuoti HTTP arba duomenų bazės klientus, kai pasikeičia atitinkama konfigūracija, o tai gali sukelti problemų. Tačiau kai kurie klientai, pavyzdžiui, „Cassandra“ tvarkyklė, skirta „Java“, palaiko automatinį konfigūracijų perkėlimą, supaprastindama šį procesą.
Iš naujo įkeliamų konfigūracijų įdiegimas gali sušvelninti neigiamą ilgo programos paleidimo laiko poveikį ir pasiūlyti papildomų privalumų, pvz., palengvinti funkcijų žymų diegimą. Šis metodas leidžia išlaikyti programos patikimumą ir reagavimą efektyviai valdant konfigūracijos naujinimus.
Dabar pažvelkime į kitą problemą: mūsų sistemoje, kai gaunama vartotojo užklausa ir apdorojama siunčiant užklausą į užpakalinę sistemą arba duomenų bazę, kartais vietoj laukiamų duomenų gaunamas atsakymas į klaidą. Vėliau mūsų sistema vartotojui atsako „klaida“.
Tačiau daugeliu atvejų gali būti geriau rodyti šiek tiek pasenusius duomenis kartu su pranešimu, rodančiu, kad yra duomenų atnaujinimo delsa, o ne palikti vartotojui didelį raudoną klaidos pranešimą.
Norėdami išspręsti šią problemą ir pagerinti sistemos veikimą, galime įdiegti atsarginį modelį. Šio modelio koncepcija apima antrinį duomenų šaltinį, kuriame gali būti prastesnės kokybės arba naujesni duomenys, palyginti su pirminiu šaltiniu. Jei pirminis duomenų šaltinis nepasiekiamas arba pateikia klaidą, sistema gali grįžti prie duomenų gavimo iš šio antrinio šaltinio, užtikrindama, kad vartotojui būtų pateikta tam tikra informacija, o ne rodomas klaidos pranešimas.
Jei pažvelgsite į aukščiau pateiktą paveikslėlį, pastebėsite panašumą tarp problemos, su kuria susiduriame dabar, ir problemos, su kuria susidūrėme su talpyklos pavyzdžiu.
Norėdami tai išspręsti, galime apsvarstyti galimybę įdiegti modelį, vadinamą pakartotiniu bandymu. Užuot pasikliaujant talpyklomis, sistema gali būti sukurta taip, kad įvykus klaidai automatiškai išsiųstų užklausą. Šis pakartotinio bandymo modelis siūlo paprastesnę alternatyvą ir gali veiksmingai sumažinti klaidų tikimybę mūsų programoje. Skirtingai nuo kaupimo talpykloje, kuriai dažnai reikia sudėtingų talpyklos negaliojimo mechanizmų, kad būtų galima apdoroti duomenų pakeitimus, nepavykusių užklausų pakartotinis bandymas yra gana paprastas. Kadangi talpyklos pripažinimas negaliojančia yra plačiai vertinamas kaip viena sudėtingiausių užduočių programinės įrangos inžinerijoje, taikant pakartotinio bandymo strategiją galima supaprastinti klaidų tvarkymą ir pagerinti sistemos atsparumą.
Tačiau pakartotinio bandymo strategijos priėmimas neatsižvelgiant į galimas pasekmes gali sukelti papildomų komplikacijų.
Įsivaizduokime, kad vienas iš mūsų užpakalinių sistemų patiria nesėkmę. Esant tokiam scenarijui, pradėjus pakartotinius bandymus į sugedusią vidinę programą, srautas gali labai padidėti. Šis staigus srauto padidėjimas gali apsunkinti užpakalinę sistemą, pabloginti gedimą ir gali sukelti pakopinį efektą visoje sistemoje.
Norint susidoroti su šiuo iššūkiu, svarbu pakartotinio bandymo modelį papildyti grandinės pertraukiklio modeliu. Grandinės pertraukiklis tarnauja kaip apsaugos mechanizmas, kuris stebi tolesnių paslaugų klaidų lygį. Kai klaidų lygis viršija iš anksto nustatytą slenkstį, grandinės pertraukiklis pertraukia užklausas į paveiktą paslaugą nurodytam laikui. Per šį laikotarpį sistema susilaiko nuo papildomų užklausų siuntimo, kad sugedusi paslauga galėtų atsistatyti. Praėjus nustatytam intervalui, grandinės pertraukiklis atsargiai leidžia perduoti ribotą užklausų skaičių, patikrindamas, ar paslauga stabilizavosi. Jei paslauga atsigavo, normalus eismas palaipsniui atkuriamas; kitu atveju grandinė lieka atvira ir toliau blokuoja užklausas, kol paslauga vėl pradės veikti normaliai. Integruodami grandinės pertraukiklio modelį kartu su pakartotinio bandymo logika, galime efektyviai valdyti klaidų situacijas ir užkirsti kelią sistemos perkrovai, kai įvyksta pagrindinės sistemos gedimai.
Apibendrinant galima pasakyti, kad įdiegę šiuos atsparumo modelius galime sustiprinti savo programas nuo kritinių situacijų, išlaikyti aukštą pasiekiamumą ir užtikrinti sklandų naudotojų patirtį. Be to, norėčiau pabrėžti, kad telemetrija yra dar viena priemonė, kurios nereikėtų pamiršti užtikrinant projekto atsparumą. Geri žurnalai ir metrika gali žymiai pagerinti paslaugų kokybę ir suteikti vertingų įžvalgų apie jų našumą ir padėti priimti pagrįstus sprendimus, kaip toliau jas tobulinti.