![Search icon](https://hackernoon.imgix.net/search-new.png?w=19&h=19)
Veerkragtigheid in sagteware verwys na die vermoë van 'n toepassing om glad en betroubaar te bly funksioneer, selfs in die lig van onverwagte probleme of mislukkings. In Fintech-projekte is veerkragtigheid veral van groot belang weens verskeie redes. Eerstens word maatskappye verplig om aan regulatoriese vereistes te voldoen en finansiële reguleerders beklemtoon operasionele veerkragtigheid om stabiliteit binne die stelsel te handhaaf. Boonop stel die verspreiding van digitale gereedskap en vertroue op derdeparty-diensverskaffers Fintech-besighede bloot aan verhoogde sekuriteitsbedreigings. Veerkragtigheid help ook om die risiko's van onderbrekings wat veroorsaak word deur verskeie faktore soos kuberbedreigings, pandemies of geopolitieke gebeure te verminder, om kernbesigheidsbedrywighede en kritieke bates te beskerm.
Deur veerkragtigheidspatrone verstaan ons 'n stel beste praktyke en strategieë wat ontwerp is om te verseker dat sagteware ontwrigtings kan weerstaan en sy bedrywighede kan onderhou. Hierdie patrone tree op soos veiligheidsnette, wat meganismes verskaf om foute te hanteer, vrag te bestuur en van mislukkings te herstel, en sodoende te verseker dat toepassings robuust en betroubaar bly onder ongunstige toestande.
Die mees algemene veerkragtigheidstrategieë sluit in skottel, kas, terugval, herprobeer en stroombreker. In hierdie artikel sal ek hulle in meer besonderhede bespreek, met voorbeelde van probleme wat hulle kan help om op te los.
Kom ons kyk na die bogenoemde instelling. Ons het 'n baie gewone toepassing met verskeie backends agter ons om data van te kry. Daar is verskeie HTTP-kliënte wat aan hierdie backends gekoppel is. Dit blyk dat almal van hulle dieselfde verbindingspoel deel! En ook ander hulpbronne soos SVE en RAM.
Wat sal gebeur, as een van die backends 'n soort probleme ondervind wat lei tot 'n hoë versoeklatentie? As gevolg van die hoë reaksietyd, sal die hele verbindingspoel ten volle beset word deur versoeke wat wag vir antwoorde van backend1. Gevolglik sal versoeke wat bedoel is vir die gesonde agterkant2 en agterkant3 nie kan voortgaan nie omdat die swembad uitgeput is. Dit beteken dat 'n mislukking in een van ons backends 'n mislukking oor die hele toepassing kan veroorsaak. Ideaal gesproke wil ons hê dat slegs die funksionaliteit wat met die mislukte agterkant geassosieer word, agteruitgang moet ervaar, terwyl die res van die toepassing voortgaan om normaal te werk.
Wat is die skottelpatroon?
Die term, Bulkhead pattern, is afgelei van skeepsbou, dit behels die skep van verskeie geïsoleerde kompartemente binne 'n skip. As 'n lekkasie in een kompartement voorkom, vul dit met water, maar die ander kompartemente bly onaangeraak. Hierdie isolasie verhoed dat die hele vaartuig sink as gevolg van 'n enkele breuk.
Die Bulkhead-patroon kan gebruik word om verskeie soorte hulpbronne binne 'n toepassing te isoleer, wat voorkom dat 'n fout in een deel die hele stelsel beïnvloed. Hier is hoe ons dit op ons probleem kan toepas:
Kom ons veronderstel ons backend-stelsels het 'n lae waarskynlikheid om individueel foute teë te kom. Wanneer 'n bewerking egter behels dat al hierdie backends parallel navraag gedoen word, kan elkeen onafhanklik 'n fout terugstuur. Omdat hierdie foute onafhanklik voorkom, is die algehele waarskynlikheid van 'n fout in ons toepassing hoër as die foutwaarskynlikheid van enige enkele agterkant. Die kumulatiewe foutwaarskynlikheid kan bereken word deur die formule P_total=1−(1−p)^n, waar n die aantal backend-stelsels is, te gebruik.
Byvoorbeeld, as ons tien backends het, elk met 'n foutwaarskynlikheid van p=0.001 (wat ooreenstem met 'n SLA van 99.9%), is die gevolglike foutwaarskynlikheid:
P_totaal=1−(1−0,001)^10=0,009955
Dit beteken dat ons gekombineerde SLA tot ongeveer 99% daal, wat illustreer hoe die algehele betroubaarheid afneem wanneer daar navraag gedoen word na verskeie backends in parallel. Om hierdie probleem te versag, kan ons 'n in-geheue-kas implementeer.
'n In-geheue-kas dien as 'n hoë-spoed data buffer, stoor gereelde toegang tot data en elimineer die behoefte om dit elke keer van potensieel stadige bronne te gaan haal. Aangesien kas wat in die geheue gestoor is, 'n 0% kans op foute het in vergelyking met die haal van data oor die netwerk, verhoog dit die betroubaarheid van ons toepassing aansienlik. Boonop verminder caching netwerkverkeer, wat die kans op foute verder verlaag. Gevolglik, deur gebruik te maak van 'n in-geheue-kas, kan ons 'n selfs laer foutkoers in ons toepassing bereik in vergelyking met ons backend-stelsels. Boonop bied in-geheue-kas vinniger data-herwinning as netwerk-gebaseerde haal, waardeur die vertraging van toepassings verminder word - 'n noemenswaardige voordeel.
Vir gepersonaliseerde data, soos gebruikersprofiele of aanbevelings, kan die gebruik van in-geheue-kas ook baie effektief wees. Maar ons moet verseker dat alle versoeke van 'n gebruiker konsekwent na dieselfde toepassingsinstansie gaan om data wat vir hulle in die kas gestoor is, te gebruik, wat taai sessies vereis. Die implementering van taai sessies kan uitdagend wees, maar vir hierdie scenario het ons nie komplekse meganismes nodig nie. Geringe verkeersherbalansering is aanvaarbaar, so 'n stabiele lasbalanseringsalgoritme soos konsekwente hashing sal voldoende wees.
Wat meer is, in die geval van 'n knooppuntfout, verseker konsekwente hashing dat slegs die gebruikers wat met die mislukte knoop geassosieer word, herbalansering ondergaan, wat ontwrigting van die stelsel tot die minimum beperk. Hierdie benadering vergemaklik die bestuur van gepersonaliseerde kas en verbeter die algehele stabiliteit en werkverrigting van ons toepassing.
As die data wat ons van plan is om te kas krities is en gebruik word in elke versoek wat ons stelsel hanteer, soos toegangsbeleide, intekeningplanne of ander belangrike entiteite in ons domein—die bron van hierdie data kan 'n beduidende punt van mislukking in ons stelsel inhou. Om hierdie uitdaging aan te spreek, is een benadering om hierdie data volledig direk in die geheue van ons toepassing te repliseer.
In hierdie scenario, as die volume data in die bron hanteerbaar is, kan ons die proses begin deur 'n momentopname van hierdie data aan die begin van ons toepassing af te laai. Vervolgens kan ons opdateringsgebeurtenisse ontvang om te verseker dat die data in die kas met die bron gesinchroniseer bly. Deur hierdie metode aan te neem, verbeter ons die betroubaarheid van toegang tot hierdie belangrike data, aangesien elke herwinning direk uit die geheue plaasvind met 'n 0% foutwaarskynlikheid. Boonop is die herwinning van data uit die geheue buitengewoon vinnig, waardeur die werkverrigting van ons toepassing geoptimaliseer word. Hierdie strategie verminder effektief die risiko verbonde aan die vertroue op 'n eksterne databron, wat konsekwente en betroubare toegang tot kritieke inligting vir ons toepassing se werking verseker.
Die behoefte om data af te laai tydens die opstart van toepassings, en sodoende die opstartproses vertraag, oortree egter een van die beginsels van die '12-faktor-toepassing' wat vir vinnige aanvang van toepassings voorstaan. Maar ons wil nie die voordele van die gebruik van caching verbeur nie. Om hierdie dilemma aan te spreek, laat ons potensiële oplossings ondersoek.
Vinnige opstart is van kardinale belang, veral vir platforms soos Kubernetes, wat staatmaak op vinnige toepassingsmigrasie na verskillende fisiese nodusse. Gelukkig kan Kubernetes programme bestuur wat stadig begin deur middel van kenmerke soos opstartprobes.
Nog 'n uitdaging wat ons in die gesig staar, is die opdatering van konfigurasies terwyl die toepassing loop. Dikwels is die aanpassing van kastye of versoek-timeouts nodig om produksiekwessies op te los. Selfs al kan ons vinnig opgedateerde konfigurasielêers na ons toepassing ontplooi, vereis die toepassing van hierdie veranderinge gewoonlik 'n herbegin. Met elke toepassing se verlengde opstarttyd kan 'n deurlopende herbegin die implementering van regstellings aan ons gebruikers aansienlik vertraag.
Om dit aan te pak, is een oplossing om konfigurasies in 'n gelyktydige veranderlike te stoor en 'n agtergronddraad dit periodiek op te dateer. Sekere parameters, soos HTTP-versoek-time-outs, kan egter vereis dat HTTP of databasiskliënte herinitialiseer word wanneer die ooreenstemmende konfigurasie verander, wat 'n potensiële uitdaging inhou. Tog ondersteun sommige kliënte, soos die Cassandra-bestuurder vir Java, outomatiese herlaai van konfigurasies, wat hierdie proses vereenvoudig.
Die implementering van herlaaibare konfigurasies kan die negatiewe impak van lang toepassings se opstarttye versag en bied bykomende voordele, soos die fasilitering van kenmerkvlag-implementerings. Hierdie benadering stel ons in staat om toepassingsbetroubaarheid en responsiwiteit te handhaaf, terwyl konfigurasieopdaterings doeltreffend bestuur word.
Kom ons kyk nou na 'n ander probleem: in ons stelsel, wanneer 'n gebruikerversoek ontvang en verwerk word deur 'n navraag na 'n backend of databasis te stuur, word soms 'n foutreaksie ontvang in plaas van die verwagte data. Vervolgens reageer ons stelsel op die gebruiker met 'n 'fout'.
In baie scenario's kan dit egter meer verkieslik wees om effens verouderde data te vertoon saam met 'n boodskap wat aandui dat daar 'n dataverversingsvertraging is, eerder as om die gebruiker met 'n groot rooi foutboodskap te laat.
Om hierdie probleem aan te spreek en ons stelsel se gedrag te verbeter, kan ons die Terugvalpatroon implementeer. Die konsep agter hierdie patroon behels om 'n sekondêre databron te hê, wat data van laer gehalte of varsheid kan bevat in vergelyking met die primêre bron. As die primêre databron onbeskikbaar is of 'n fout terugstuur, kan die stelsel terugval om data van hierdie sekondêre bron af te haal, om te verseker dat een of ander vorm van inligting aan die gebruiker aangebied word in plaas daarvan om 'n foutboodskap te vertoon.
As jy na die prentjie hierbo kyk, sal jy 'n ooreenkoms sien tussen die probleem wat ons nou in die gesig staar en die een wat ons met die kasvoorbeeld teëgekom het.
Om dit op te los, kan ons dit oorweeg om 'n patroon bekend as herprobeer te implementeer. In plaas daarvan om op caches staat te maak, kan die stelsel ontwerp word om die versoek outomaties weer te stuur in die geval van 'n fout. Hierdie herprobeerpatroon bied 'n eenvoudiger alternatief en kan die waarskynlikheid van foute in ons toepassing effektief verminder. In teenstelling met cache, wat dikwels komplekse kas ongeldigmaking meganismes vereis om data veranderinge te hanteer, is die herprobering van mislukte versoeke relatief eenvoudig om te implementeer. Aangesien kas ongeldigmaking algemeen beskou word as een van die mees uitdagende take in sagteware-ingenieurswese, kan die aanvaarding van 'n herprobeer-strategie fouthantering stroomlyn en stelselveerkragtigheid verbeter.
Die aanvaarding van 'n herprobeerstrategie sonder om moontlike gevolge in ag te neem, kan egter tot verdere komplikasies lei.
Kom ons verbeel ons een van ons backends ervaar 'n mislukking. In so 'n scenario kan die aanvang van herprobasies na die mislukte backend 'n aansienlike toename in verkeersvolume tot gevolg hê. Hierdie skielike oplewing in verkeer kan die agterkant oorweldig, die mislukking vererger en moontlik 'n kaskade-effek oor die stelsel veroorsaak.
Om hierdie uitdaging die hoof te bied, is dit belangrik om die herprobeerpatroon met die stroombrekerpatroon aan te vul. Die stroombreker dien as 'n beskermingsmeganisme wat die foutkoers van stroomaf-dienste monitor. Wanneer die foutkoers 'n voorafbepaalde drempel oorskry, onderbreek die stroombreker versoeke aan die geaffekteerde diens vir 'n bepaalde duur. Gedurende hierdie tydperk weerhou die stelsel om bykomende versoeke te stuur om die mislukte dienstyd te laat herstel. Na die aangewese interval laat die stroombreker versigtig 'n beperkte aantal versoeke deur, om te verifieer of die diens gestabiliseer het. As die diens herstel het, word normale verkeer geleidelik herstel; anders bly die kring oop en gaan voort om versoeke te blokkeer totdat die diens normale werking hervat. Deur die stroombrekerpatroon saam met herprobeerlogika te integreer, kan ons foutsituasies effektief bestuur en stelseloorlading tydens backend-foute voorkom.
Ten slotte, deur hierdie veerkragtigheidspatrone te implementeer, kan ons ons toepassings teen noodgevalle versterk, hoë beskikbaarheid handhaaf en 'n naatlose ervaring aan gebruikers lewer. Verder wil ek beklemtoon dat telemetrie nog 'n instrument is wat nie oor die hoof gesien moet word wanneer projekveerkragtigheid verskaf word nie. Goeie logs en maatstawwe kan die gehalte van dienste aansienlik verbeter en waardevolle insigte in hul prestasie verskaf, wat help om ingeligte besluite te neem om dit verder te verbeter.