Modele të përshtatshme arkitekturore

Hej Habr!

Në dritën e ngjarjeve aktuale për shkak të koronavirusit, një numër shërbimesh interneti kanë filluar të marrin ngarkesë të shtuar. Për shembull, Një nga zinxhirët e shitjeve me pakicë në Mbretërinë e Bashkuar thjesht ndaloi faqen e tij të porositjes në internet., sepse nuk kishte kapacitet të mjaftueshëm. Dhe nuk është gjithmonë e mundur të shpejtosh një server thjesht duke shtuar pajisje më të fuqishme, por kërkesat e klientëve duhet të përpunohen (ose ato do të shkojnë te konkurrentët).

Në këtë artikull do të flas shkurtimisht për praktikat e njohura që do t'ju lejojnë të krijoni një shërbim të shpejtë dhe tolerant ndaj gabimeve. Megjithatë, nga skemat e mundshme të zhvillimit, përzgjodha vetëm ato që janë aktualisht lehtë për t'u përdorur. Për çdo artikull, ose keni biblioteka të gatshme, ose keni mundësinë ta zgjidhni problemin duke përdorur një platformë cloud.

Shkallëzimi horizontal

Pika më e thjeshtë dhe më e njohur. Në mënyrë konvencionale, dy skemat më të zakonshme të shpërndarjes së ngarkesës janë shkallëzimi horizontal dhe vertikal. Në një rast të përhershëm ju lejoni që shërbimet të funksionojnë paralelisht, duke shpërndarë kështu ngarkesën ndërmjet tyre. Në të dytën ju porositni serverë më të fuqishëm ose optimizoni kodin.

Për shembull, unë do të marr ruajtje abstrakte të skedarëve cloud, domethënë një analog të OwnCloud, OneDrive, e kështu me radhë.

Një fotografi standarde e një qarku të tillë është më poshtë, por ajo tregon vetëm kompleksitetin e sistemit. Në fund të fundit, ne duhet të sinkronizojmë disi shërbimet. Çfarë ndodh nëse përdoruesi ruan një skedar nga tableti dhe më pas dëshiron ta shikojë atë nga telefoni?

Modele të përshtatshme arkitekturore
Dallimi midis qasjeve: në shkallëzimin vertikal, ne jemi gati të rrisim fuqinë e nyjeve, dhe në shkallëzimin horizontal, jemi gati të shtojmë nyje të reja për të shpërndarë ngarkesën.

CQRS

Ndarja e përgjegjësisë së pyetjes së komandës Një model mjaft i rëndësishëm, pasi lejon klientë të ndryshëm jo vetëm të lidhen me shërbime të ndryshme, por edhe të marrin të njëjtat transmetime ngjarjesh. Përfitimet e tij nuk janë aq të dukshme për një aplikim të thjeshtë, por është jashtëzakonisht i rëndësishëm (dhe i thjeshtë) për një shërbim të ngarkuar. Thelbi i saj: flukset e të dhënave hyrëse dhe dalëse nuk duhet të kryqëzohen. Kjo do të thotë, ju nuk mund të dërgoni një kërkesë dhe të prisni një përgjigje; në vend të kësaj, ju dërgoni një kërkesë në shërbimin A, por merrni një përgjigje nga shërbimi B.

Bonusi i parë i kësaj qasjeje është aftësia për të prishur lidhjen (në kuptimin e gjerë të fjalës) gjatë ekzekutimit të një kërkese të gjatë. Për shembull, le të marrim një sekuencë pak a shumë standarde:

  1. Klienti dërgoi një kërkesë në server.
  2. Serveri filloi një kohë të gjatë përpunimi.
  3. Serveri iu përgjigj klientit me rezultatin.

Le të imagjinojmë që në pikën 2 lidhja është prishur (ose rrjeti është rilidhur, ose përdoruesi ka shkuar në një faqe tjetër, duke prishur lidhjen). Në këtë rast, do të jetë e vështirë për serverin t'i dërgojë një përgjigje përdoruesit me informacione se çfarë saktësisht është përpunuar. Duke përdorur CQRS, sekuenca do të jetë paksa e ndryshme:

  1. Klienti është abonuar në përditësimet.
  2. Klienti dërgoi një kërkesë në server.
  3. Serveri u përgjigj "kërkesa u pranua".
  4. Serveri u përgjigj me rezultatin përmes kanalit nga pika "1".

Modele të përshtatshme arkitekturore

Siç mund ta shihni, skema është pak më e ndërlikuar. Për më tepër, këtu mungon qasja intuitive e kërkesë-përgjigjes. Sidoqoftë, siç mund ta shihni, një ndërprerje e lidhjes gjatë përpunimit të një kërkese nuk do të çojë në një gabim. Për më tepër, nëse në fakt përdoruesi është i lidhur me shërbimin nga disa pajisje (për shembull, nga një telefon celular dhe nga një tablet), mund të siguroheni që përgjigja të vijë në të dyja pajisjet.

Është interesante se kodi për përpunimin e mesazheve hyrëse bëhet i njëjtë (jo 100%) si për ngjarjet që janë ndikuar nga vetë klienti, ashtu edhe për ngjarje të tjera, përfshirë ato nga klientët e tjerë.

Sidoqoftë, në realitet ne marrim një bonus shtesë për faktin se rrjedha e njëanshme mund të trajtohet në një stil funksional (duke përdorur RX dhe të ngjashme). Dhe ky është tashmë një plus serioz, pasi në thelb aplikacioni mund të bëhet plotësisht reaktiv, dhe gjithashtu duke përdorur një qasje funksionale. Për programet e majme, kjo mund të kursejë ndjeshëm burimet e zhvillimit dhe mbështetjes.

Nëse e kombinojmë këtë qasje me shkallëzimin horizontal, atëherë si bonus marrim mundësinë për të dërguar kërkesa në një server dhe për të marrë përgjigje nga një tjetër. Kështu, klienti mund të zgjedhë shërbimin që është i përshtatshëm për të, dhe sistemi brenda do të jetë ende në gjendje të përpunojë ngjarjet në mënyrë korrekte.

Burimi i ngjarjeve

Siç e dini, një nga karakteristikat kryesore të një sistemi të shpërndarë është mungesa e një kohe të përbashkët, një seksion kritik të përbashkët. Për një proces, mund të bëni një sinkronizim (në të njëjtat mutexes), brenda të cilit jeni të sigurt se askush tjetër nuk po e ekzekuton këtë kod. Sidoqoftë, kjo është e rrezikshme për një sistem të shpërndarë, pasi do të kërkojë shpenzime të larta, dhe gjithashtu do të vrasë gjithë bukurinë e shkallëzimit - të gjithë përbërësit do të presin ende për një.

Nga këtu marrim një fakt të rëndësishëm - një sistem i shpërndarë shpejt nuk mund të sinkronizohet, sepse atëherë do të zvogëlojmë performancën. Nga ana tjetër, shpesh kemi nevojë për një konsistencë të caktuar midis komponentëve. Dhe për këtë ju mund të përdorni qasjen me konsistencë eventuale, ku garantohet se nëse nuk ka ndryshime të të dhënave për një periudhë kohore pas përditësimit të fundit (“përfundimisht”), të gjitha pyetjet do të kthejnë vlerën e fundit të përditësuar.

Është e rëndësishme të kuptohet se për bazat e të dhënave klasike përdoret mjaft shpesh qëndrueshmëri e fortë, ku çdo nyje ka të njëjtin informacion (kjo arrihet shpesh në rastin kur transaksioni konsiderohet i vendosur vetëm pasi serveri i dytë të përgjigjet). Këtu ka disa relaksime për shkak të niveleve të izolimit, por ideja e përgjithshme mbetet e njëjtë - ju mund të jetoni në një botë plotësisht të harmonizuar.

Megjithatë, le të kthehemi në detyrën fillestare. Nëse një pjesë e sistemit mund të ndërtohet me konsistencë eventuale, atëherë mund të ndërtojmë diagramin e mëposhtëm.

Modele të përshtatshme arkitekturore

Karakteristikat e rëndësishme të kësaj qasjeje:

  • Çdo kërkesë hyrëse vendoset në një radhë.
  • Gjatë përpunimit të një kërkese, shërbimi mund të vendosë detyra edhe në radhë të tjera.
  • Çdo ngjarje hyrëse ka një identifikues (i cili është i nevojshëm për deduplikim).
  • Radha funksionon ideologjikisht sipas skemës "vetëm shtoj". Ju nuk mund të hiqni elementë prej tij ose t'i riorganizoni ato.
  • Radha funksionon sipas skemës FIFO (më falni për tautologjinë). Nëse keni nevojë të bëni ekzekutim paralel, atëherë në një fazë duhet të zhvendosni objektet në radhë të ndryshme.

Më lejoni t'ju kujtoj se ne po shqyrtojmë rastin e ruajtjes së skedarëve në internet. Në këtë rast, sistemi do të duket diçka si kjo:

Modele të përshtatshme arkitekturore

Është e rëndësishme që shërbimet në diagram të mos nënkuptojnë domosdoshmërisht një server të veçantë. Edhe procesi mund të jetë i njëjtë. Një gjë tjetër është e rëndësishme: ideologjikisht, këto gjëra janë të ndara në atë mënyrë që shkallëzimi horizontal mund të zbatohet lehtësisht.

Dhe për dy përdorues, diagrami do të duket kështu (shërbimet e destinuara për përdorues të ndryshëm tregohen me ngjyra të ndryshme):

Modele të përshtatshme arkitekturore

Bonuset nga një kombinim i tillë:

  • Shërbimet e përpunimit të informacionit janë të ndara. Janë të ndara edhe radhët. Nëse na duhet të rrisim xhiron e sistemit, atëherë thjesht duhet të lëshojmë më shumë shërbime në më shumë serverë.
  • Kur marrim informacion nga një përdorues, nuk duhet të presim derisa të dhënat të ruhen plotësisht. Përkundrazi, ne vetëm duhet të përgjigjemi "ok" dhe pastaj gradualisht të fillojmë të punojmë. Në të njëjtën kohë, radha zbut majat, pasi shtimi i një objekti të ri ndodh shpejt, dhe përdoruesi nuk duhet të presë për një kalim të plotë në të gjithë ciklin.
  • Si shembull, shtova një shërbim deduplication që përpiqet të bashkojë skedarë identikë. Nëse funksionon për një kohë të gjatë në 1% të rasteve, klienti vështirë se do ta vërejë atë (shih më lart), që është një plus i madh, pasi nuk na kërkohet më të jemi XNUMX% shpejtësi dhe të besueshëm.

Sidoqoftë, disavantazhet janë menjëherë të dukshme:

  • Sistemi ynë ka humbur qëndrueshmërinë e tij të rreptë. Kjo do të thotë që nëse, për shembull, abonoheni në shërbime të ndryshme, atëherë teorikisht mund të merrni një gjendje të ndryshme (pasi një nga shërbimet mund të mos ketë kohë për të marrë një njoftim nga radha e brendshme). Si pasojë tjetër, sistemi tani nuk ka kohë të përbashkët. Kjo do të thotë, është e pamundur, për shembull, të renditni të gjitha ngjarjet thjesht sipas kohës së mbërritjes, pasi orët midis serverëve mund të mos jenë sinkron (për më tepër, e njëjta kohë në dy serverë është një utopi).
  • Asnjë ngjarje tani thjesht nuk mund të rikthehet (siç mund të bëhej me një bazë të dhënash). Në vend të kësaj, ju duhet të shtoni një ngjarje të re − ngjarje kompensimi, e cila do të ndryshojë gjendjen e fundit në atë të kërkuar. Si shembull nga një zonë e ngjashme: pa rishkruar historinë (që është e keqe në disa raste), nuk mund të kthesh një commit në git, por mund të bësh një speciale kthim mbrapsht commit, e cila në thelb sapo kthen gjendjen e vjetër. Megjithatë, si kryerja e gabuar ashtu edhe rikthimi do të mbeten në histori.
  • Skema e të dhënave mund të ndryshojë nga publikimi në publikim, por ngjarjet e vjetra nuk do të mund të përditësohen më me standardin e ri (pasi ngjarjet nuk mund të ndryshohen në parim).

Siç mund ta shihni, Event Sourcing funksionon mirë me CQRS. Për më tepër, zbatimi i një sistemi me radhë efikase dhe të përshtatshme, por pa ndarje të rrjedhave të të dhënave, është tashmë i vështirë në vetvete, sepse do të duhet të shtoni pika sinkronizimi që do të neutralizojnë të gjithë efektin pozitiv të radhëve. Duke aplikuar të dyja qasjet menjëherë, është e nevojshme të rregulloni pak kodin e programit. Në rastin tonë, kur dërgoni një skedar në server, përgjigja vjen vetëm "ok", që do të thotë vetëm se "operacioni i shtimit të skedarit u ruajt". Formalisht, kjo nuk do të thotë që të dhënat janë tashmë të disponueshme në pajisje të tjera (për shembull, shërbimi i deduplication mund të rindërtojë indeksin). Sidoqoftë, pas ca kohësh, klienti do të marrë një njoftim në stilin "skedari X është ruajtur".

Si rezultat:

  • Numri i statuseve të dërgimit të skedarëve po rritet: në vend të "skedarit të dërguar" klasik, marrim dy: "skedari është shtuar në radhë në server" dhe "skedari është ruajtur në ruajtje". Kjo e fundit do të thotë që pajisjet e tjera tashmë mund të fillojnë të marrin skedarin (rregulluar për faktin që radhët funksionojnë me shpejtësi të ndryshme).
  • Për shkak të faktit se informacioni i dorëzimit tani vjen përmes kanaleve të ndryshme, ne duhet të gjejmë zgjidhje për të marrë statusin e përpunimit të skedarit. Si pasojë e kësaj: ndryshe nga kërkesa-përgjigje klasike, klienti mund të riniset gjatë përpunimit të skedarit, por vetë statusi i këtij përpunimi do të jetë i saktë. Për më tepër, ky artikull funksionon, në thelb, jashtë kutisë. Si pasojë: tani jemi më tolerantë ndaj dështimeve.

copëzimi

Siç u përshkrua më lart, sistemeve të burimit të ngjarjeve u mungon konsistenca strikte. Kjo do të thotë që ne mund të përdorim disa depo pa ndonjë sinkronizim mes tyre. Duke iu afruar problemit tonë, ne mund të:

  • Ndani skedarët sipas llojit. Për shembull, fotografitë/videot mund të dekodohen dhe mund të zgjidhet një format më efikas.
  • Ndani llogaritë sipas vendit. Për shkak të shumë ligjeve, kjo mund të kërkohet, por kjo skemë arkitekturore e ofron një mundësi të tillë automatikisht

Modele të përshtatshme arkitekturore

Nëse dëshironi të transferoni të dhëna nga një memorie në tjetrën, atëherë mjetet standarde nuk janë më të mjaftueshme. Fatkeqësisht, në këtë rast, duhet të ndaloni radhën, të bëni migrimin dhe më pas ta filloni atë. Në rastin e përgjithshëm, të dhënat nuk mund të transferohen "në fluturim", megjithatë, nëse radha e ngjarjeve ruhet plotësisht dhe keni fotografi të gjendjeve të mëparshme të ruajtjes, atëherë ne mund t'i riprodhojmë ngjarjet si më poshtë:

  • Në Burimin e ngjarjes, çdo ngjarje ka identifikuesin e vet (në mënyrë ideale, jo në rënie). Kjo do të thotë se ne mund të shtojmë një fushë në ruajtje - ID-në e elementit të fundit të përpunuar.
  • Ne kopjojmë radhën në mënyrë që të gjitha ngjarjet të mund të përpunohen për disa depo të pavarura (e para është ajo në të cilën të dhënat janë ruajtur tashmë, dhe e dyta është e re, por ende bosh). Radha e dytë, natyrisht, nuk po përpunohet ende.
  • Ne nisim radhën e dytë (d.m.th., fillojmë të riprodhojmë ngjarjet).
  • Kur radha e re është relativisht bosh (d.m.th., diferenca mesatare e kohës midis shtimit të një elementi dhe marrjes së tij është e pranueshme), mund të filloni të kaloni lexuesit në hapësirën e re të ruajtjes.

Siç mund ta shihni, ne nuk kemi pasur dhe nuk kemi ende konsistencë strikte në sistemin tonë. Ekziston vetëm qëndrueshmëri eventuale, domethënë një garanci që ngjarjet të përpunohen në të njëjtin rend (por mundësisht me vonesa të ndryshme). Dhe, duke përdorur këtë, ne mund të transferojmë relativisht lehtë të dhëna pa e ndaluar sistemin në anën tjetër të globit.

Kështu, duke vazhduar shembullin tonë në lidhje me ruajtjen në internet të skedarëve, një arkitekturë e tillë tashmë na jep një numër bonusesh:

  • Ne mund t'i lëvizim objektet më afër përdoruesve në një mënyrë dinamike. Në këtë mënyrë ju mund të përmirësoni cilësinë e shërbimit.
  • Ne mund të ruajmë disa të dhëna brenda kompanive. Për shembull, përdoruesit e Enterprise shpesh kërkojnë që të dhënat e tyre të ruhen në qendra të kontrolluara të të dhënave (për të shmangur rrjedhjet e të dhënave). Nëpërmjet ndarjes ne mund ta mbështesim lehtësisht këtë. Dhe detyra është edhe më e lehtë nëse klienti ka një re të pajtueshme (për shembull, Azure vetë priti).
  • Dhe gjëja më e rëndësishme është që ne nuk duhet ta bëjmë këtë. Në fund të fundit, për të filluar, do të ishim mjaft të kënaqur me një hapësirë ​​ruajtëse për të gjitha llogaritë (për të filluar punën shpejt). Dhe tipari kryesor i këtij sistemi është se megjithëse është i zgjerueshëm, në fazën fillestare është mjaft i thjeshtë. Thjesht nuk duhet të shkruani menjëherë kodin që funksionon me një milion radhë të veçanta të pavarura, etj. Nëse është e nevojshme, kjo mund të bëhet në të ardhmen.

Pritja e përmbajtjes statike

Kjo pikë mund të duket mjaft e qartë, por është ende e nevojshme për një aplikacion të ngarkuar pak a shumë standard. Thelbi i tij është i thjeshtë: e gjithë përmbajtja statike shpërndahet jo nga i njëjti server ku ndodhet aplikacioni, por nga ato speciale të dedikuara posaçërisht për këtë detyrë. Si rezultat, këto operacione kryhen më shpejt (nginx i kushtëzuar i shërben skedarëve më shpejt dhe më pak shtrenjtë se një server Java). Plus arkitekturë CDN (Dorëzimit Content Network-) na lejon të lokalizojmë skedarët tanë më afër përdoruesve fundorë, gjë që ka një efekt pozitiv në komoditetin e punës me shërbimin.

Shembulli më i thjeshtë dhe më standard i përmbajtjes statike është një grup skriptesh dhe imazhesh për një faqe interneti. Gjithçka është e thjeshtë me ta - ato njihen paraprakisht, më pas arkivi ngarkohet në serverët CDN, nga ku ato shpërndahen tek përdoruesit përfundimtarë.

Sidoqoftë, në realitet, për përmbajtjen statike, mund të përdorni një qasje disi të ngjashme me arkitekturën lambda. Le të kthehemi te detyra jonë (ruajtja e skedarëve në internet), në të cilën duhet të shpërndajmë skedarët tek përdoruesit. Zgjidhja më e thjeshtë është krijimi i një shërbimi që, për çdo kërkesë të përdoruesit, bën të gjitha kontrollet e nevojshme (autorizim, etj.), dhe më pas shkarkon skedarin direkt nga ruajtja jonë. Disavantazhi kryesor i kësaj qasjeje është se përmbajtja statike (dhe një skedar me një rishikim të caktuar është, në fakt, përmbajtje statike) shpërndahet nga i njëjti server që përmban logjikën e biznesit. Në vend të kësaj, mund të bëni diagramin e mëposhtëm:

  • Serveri ofron një URL shkarkimi. Mund të jetë i formës file_id + key, ku çelësi është një nënshkrim mini-dixhital që jep të drejtën e aksesit në burim për XNUMX orët e ardhshme.
  • Skedari shpërndahet nga nginx i thjeshtë me opsionet e mëposhtme:
    • Memoria e përmbajtjes. Meqenëse ky shërbim mund të vendoset në një server të veçantë, ne i kemi lënë vetes një rezervë për të ardhmen me aftësinë për të ruajtur të gjithë skedarët më të fundit të shkarkuar në disk.
    • Kontrollimi i çelësit në momentin e krijimit të lidhjes
  • Opsionale: përpunimi i përmbajtjes me transmetim. Për shembull, nëse kompresojmë të gjithë skedarët në shërbim, atëherë mund të bëjmë zbërthimin direkt në këtë modul. Si pasojë: operacionet e IO bëhen aty ku i takon. Një arkivues në Java do të ndajë lehtësisht shumë memorie shtesë, por rishkrimi i një shërbimi me logjikën e biznesit në kushte Rust/C++ mund të jetë gjithashtu i paefektshëm. Në rastin tonë, përdoren procese (ose edhe shërbime) të ndryshme, dhe për këtë arsye ne mund të ndajmë në mënyrë mjaft efektive logjikën e biznesit dhe operacionet IO.

Modele të përshtatshme arkitekturore

Kjo skemë nuk është shumë e ngjashme me shpërndarjen e përmbajtjes statike (pasi ne nuk e ngarkojmë të gjithë paketën statike diku), por në realitet, kjo qasje ka të bëjë pikërisht me shpërndarjen e të dhënave të pandryshueshme. Për më tepër, kjo skemë mund të përgjithësohet në raste të tjera ku përmbajtja nuk është thjesht statike, por mund të përfaqësohet si një grup blloqesh të pandryshueshme dhe të pafshishme (edhe pse ato mund të shtohen).

Si shembull tjetër (për përforcim): nëse keni punuar me Jenkins/TeamCity, atëherë e dini që të dyja zgjidhjet janë të shkruara në Java. Të dy janë një proces Java që trajton si orkestrimin e ndërtimit ashtu edhe menaxhimin e përmbajtjes. Në veçanti, ata të dy kanë detyra si "transferimi i një skedari/dosjeje nga serveri". Si shembull: lëshimi i objekteve, transferimi i kodit burimor (kur agjenti nuk e shkarkon kodin direkt nga depoja, por serveri e bën atë për të), qasja në regjistrat. Të gjitha këto detyra ndryshojnë në ngarkesën e tyre IO. Kjo do të thotë, rezulton se serveri përgjegjës për logjikën komplekse të biznesit duhet në të njëjtën kohë të jetë në gjendje të shtyjë në mënyrë efektive flukse të mëdha të të dhënave përmes vetvetes. Dhe ajo që është më interesante është se një operacion i tillë mund të delegohet në të njëjtin nginx sipas të njëjtës skemë (përveç që çelësi i të dhënave duhet të shtohet në kërkesë).

Sidoqoftë, nëse kthehemi në sistemin tonë, marrim një diagram të ngjashëm:

Modele të përshtatshme arkitekturore

Siç mund ta shihni, sistemi është bërë rrënjësisht më kompleks. Tani nuk është vetëm një mini-proces që ruan skedarët në nivel lokal. Tani ajo që kërkohet nuk është mbështetja më e thjeshtë, kontrolli i versionit të API, etj. Prandaj, pasi të jenë vizatuar të gjitha diagramet, është më mirë të vlerësohet në detaje nëse zgjerueshmëria ia vlen kostoja. Sidoqoftë, nëse dëshironi të jeni në gjendje të zgjeroni sistemin (duke përfshirë edhe punën me një numër edhe më të madh përdoruesish), atëherë do t'ju duhet të kërkoni zgjidhje të ngjashme. Por, si rezultat, sistemi është arkitekturisht i gatshëm për ngarkesë të shtuar (pothuajse çdo komponent mund të klonohet për shkallëzim horizontal). Sistemi mund të përditësohet pa e ndaluar (thjesht disa operacione do të ngadalësohen paksa).

Siç thashë në fillim, tani një numër i shërbimeve të Internetit kanë filluar të marrin ngarkesë të shtuar. Dhe disa prej tyre thjesht filluan të ndalonin së punuari si duhet. Në fakt, sistemet dështuan pikërisht në momentin kur biznesi duhej të fitonte para. Kjo do të thotë, në vend të dërgesës së shtyrë, në vend që t'u sugjeronte klientëve "planifikoni dorëzimin për muajt e ardhshëm", sistemi thjesht tha "shkoni te konkurrentët tuaj". Në fakt, ky është çmimi i produktivitetit të ulët: humbjet do të ndodhin pikërisht kur fitimet do të ishin më të lartat.

Përfundim

Të gjitha këto qasje ishin të njohura më parë. E njëjta VK ka kohë që përdor idenë e pritjes së përmbajtjes statike për të shfaqur imazhe. Shumë lojëra në internet përdorin skemën Sharding për të ndarë lojtarët në rajone ose për të ndarë vendndodhjet e lojërave (nëse vetë bota është e tillë). Qasja e burimit të ngjarjeve përdoret në mënyrë aktive në email. Shumica e aplikacioneve tregtare ku të dhënat merren vazhdimisht janë ndërtuar në të vërtetë në një qasje CQRS në mënyrë që të jenë në gjendje të filtrojnë të dhënat e marra. Epo, shkallëzimi horizontal është përdorur në shumë shërbime për një kohë mjaft të gjatë.

Megjithatë, më e rëndësishmja, të gjitha këto modele janë bërë shumë të lehta për t'u zbatuar në aplikacionet moderne (nëse janë të përshtatshme, sigurisht). Retë ofrojnë shkallëzim Sharding dhe horizontale menjëherë, gjë që është shumë më e lehtë sesa të porosisni vetë serverë të ndryshëm të dedikuar në qendra të ndryshme të të dhënave. CQRS është bërë shumë më e lehtë, qoftë edhe për shkak të zhvillimit të bibliotekave të tilla si RX. Rreth 10 vjet më parë, një faqe interneti e rrallë mund ta mbështeste këtë. Burimi i ngjarjeve është gjithashtu tepër i lehtë për t'u vendosur falë kontejnerëve të gatshëm me Apache Kafka. 10 vjet më parë kjo do të ishte një risi, tani është e zakonshme. Është e njëjta gjë me pritjen e përmbajtjes statike: për shkak të teknologjive më të përshtatshme (përfshirë faktin se ka dokumentacion të detajuar dhe një bazë të dhënash të madhe përgjigjesh), kjo qasje është bërë edhe më e thjeshtë.

Si rezultat, zbatimi i një numri modelesh arkitekturore mjaft komplekse tani është bërë shumë më i thjeshtë, që do të thotë se është më mirë t'i hedhim një vështrim më të afërt paraprakisht. Nëse në një aplikacion dhjetëvjeçar një nga zgjidhjet e mësipërme u braktis për shkak të kostos së lartë të zbatimit dhe funksionimit, tani, në një aplikacion të ri ose pas rifaktorimit, mund të krijoni një shërbim që tashmë do të jetë arkitekturisht i shtrirë ( për sa i përket performancës) dhe të gatshme për kërkesat e reja nga klientët (për shembull, për të lokalizuar të dhënat personale).

Dhe më e rëndësishmja: ju lutemi mos i përdorni këto qasje nëse keni një aplikim të thjeshtë. Po, ato janë të bukura dhe interesante, por për një sit me një vizitë maksimale prej 100 personash, shpesh mund të kaloni me një monolit klasik (të paktën nga jashtë, gjithçka brenda mund të ndahet në module, etj.).

Burimi: www.habr.com

Shto një koment