Përshëndetje, Habr!
Në dritën e ngjarjeve aktuale për shkak të coronavirusit, një sërë shërbimesh interneti ka filluar të përjetojë një ngarkesë të rritur. Për shembull, , pasi nuk kishte kapacitete të mjaftueshme. Dhe nuk është gjithmonë e mundur të përshpejtohet serveri thjesht duke shtuar pajisje më të fuqishme, por duhen trajtuar kërkesat e klientëve (ndryshe ata do të kalojnë te konkurrentët).
Në këtë artikull, do të flas shkurtimisht për praktikat e njohura që do të lejojnë krijimin e një shërbimi të shpejtë dhe të besueshëm. Megjithatë, nga skemat e mundshme të zhvillimit, kam zgjedhur vetëm ato që tani janë lehtësisht të përdorshme. Për secilën pikë, ju ose keni biblioteka të gatshme, ose keni mundësinë të zgjidhni detyrën përmes një platforme cloud.
Zgjerimi horizontal
Pika më e thjeshtë dhe më e njohur. Në mënyrë të përgjithshme, dy skema më të zakonshme të shpërndarjes së ngarkesës janë: horizontal dhe vertikal. ju lejoni shërbimet të funksionojnë paralelisht, duke shpërndarë ngarkesën midis tyre. ju porosisni serverë më të fuqishëm ose optimizoni kodin.
Për shembull, do të marr një ruajtje të paqartë cloud, pra një disa analogji të OwnCloud, OneDrive dhe kështu me radhë.
Pamja standarde e një skeme të tillë është më poshtë, megjithatë ajo thjesht demonstruar kompleksitetin e sistemit. Sepse na nevojitet të sinkronizojmë ndonjëherë shërbimet. Çfarë do të ndodhë nëse një përdorues ruan një skedar nga tableti, dhe pastaj do ta shikojë atë nga telefoni?

Dallimi midis qasjeve: në shkallëzimin vertikal jemi të gatshëm të rrisim kapacitetet e nyjeve, ndërsa në atë horizontal — shtojmë nyje të reja për të shpërndarë ngarkesën.
CQRS
është një model quite i rëndësishëm, pasi i lejon klientëve të ndryshëm jo vetëm të lidhen me shërbime të ndryshme, por edhe të marrin rrjedha ngjarjesh identike. Benefitet e tij nuk janë aq të dukshme për një aplikacion të thjeshtë, megjithatë ai është jashtëzakonisht e rëndësishme (dhe e thjeshtë) për një shërbim të ngarkuar. Thelbi i tij: rrjedhat e dhënave hyrëse dhe dalëse nuk duhet të kalojnë. Kështu, nuk mund të dërgoni një kërkesë dhe të prisni një përgjigje, përkundrazi dërgoni një kërkesë në shërbimin A, megjithatë merrni përgjigjen në shërbimin B.
Benefiti i parë i kësaj qasje është mundësia e ndërprerjes së lidhjes (në kuptimin e gjerë të fjalës) gjatë kryerjes së një kërkese të gjatë. Për shembull, le të marrim një renditje më se standarde:
- Klienti dërgoi një kërkesë në server.
- Serveri nisi një përpunim të gjatë.
- Serveri iu përgjigj klientit me rezultatin.
Imagjinoni se në pikën 2 ndodhi një ndërprerje e lidhjes (ose rrjeti u rikonektua, ose përdoruesi kaloi në një tjetër faqe, duke shkëputur lidhjen). Në këtë rast serverit do t'i ishte e vështirë të dërgonte përgjigjen te përdoruesi me informacionin se çfarë u përpunua. Duke aplikuar CQRS, renditja do të ishte paksa ndryshe:
- Klienti u abonua për përditësime.
- Klienti dërgoi një kërkesë në server.
- Serveri iu përgjigj "kërkesa e pranuar".
- Serveri iu përgjigj rezultatit përmes kanalit nga "1".

Siç tregohet, skema është paksa më e komplikuar. Më shumë se kaq, qasja intuitivë e kërkesës dhe përgjigjes këtu mungon. Megjithatë siç duket, ndërprerja e lidhjes gjatë përpunimit të kërkesës nuk do të sjellë gabim. Më tepër, nëse përdoruesi në të vërtetë është i lidhur me shërbimin nga disa pajisje (për shembull, nga telefoni celular dhe nga tableti), është e mundur që përgjigja të vijë në të dy pajisjet.
Ajo që është interesante është se kodi i përpunimit të mesazheve hyrëse bëhet i njëjtë (jo 100%) si për ngjarjet që ndikuan vetë klientin, ashtu edhe për ngjarjet e tjera, duke përfshirë ato nga klientë të tjerë.
Megjithatë në realitet ne marrim përfitime të tjera falë faktit se rrjedha njëkahëshe mund të përpunohet në stilin funksional (duke përdorur RX dhe analogë). Dhe kjo është një përfitim i rëndësishëm, sepse në fakt aplikacioni mund të bëhet krejtësisht reaktiv, madje edhe me përdorimin e qasjeve funksionale. Për aplikacione të dhjamosura, kjo mund të ndihmojë ndjeshëm në kursimin e burimeve në zhvillim dhe mbështetje.
Nëse e kombinosh këtë qasje me shkallëzimin horizontal, atëherë si bonus ne fitojmë mundësinë për të dërguar kërkesa në një server dhe për të marrë përgjigje nga një tjetër. Në këtë mënyrë, klienti mund të zgjedhë shërbimin që i përshtatet më mirë, ndërsa sistemi brenda mund të trajtojë ngjarjet në mënyrë të saktë.
Event Sourcing
Si e dini, një nga tiparet kryesore të një sistemi të shpërndarë është mungesa e një kohe të përbashkët, një seksioni kritik të përbashkët. Për një proces mund të realizoni sinkronizimin (në të njëjtat mutex), brenda të cilit jeni të sigurt se askush tjetër nuk po e ekzekuton këtë kod. Megjithatë, për një sistem të shpërndarë diçka e tillë është e rrezikshme, sepse do të kërkonte shpenzime të larta, si dhe do të shkatërronte gjithë bukurinë e shkallëzimit - megjithatë të gjithë komponentët do të prisnin njëri-tjetrin.
Nga kjo nxjerrim një fakt të rëndësishëm - një sistem të shpërndarë të shpejtë nuk mund të sinkronizohet, sepse atëherë ne do të reduktojmë performancën. Në anën tjetër, shpesh na nevojitet një koherencë e caktuar e komponentëve. Dhe për këtë mund të përdorim qasjen me , ku garanton se në mungesë të ndryshimeve të të dhënave pas një periudhe të caktuar kohe pas azhurnimit të fundit ("fundit") të gjitha kërkesat do të kthjellin vlerën e fundit të azhurnuar.
Është e rëndësishme të kuptohet se për bazat e të dhënave klasike shpesh aplikohet , ku çdo nyje ka të njëjtat informacione (kjo shpesh arrihet kur një transaksion konsiderohet i vendosur vetëm pas përgjigjes nga serveri i dytë). Këtu ka disa lehtësira për shkak të niveleve të izolimit, megjithatë thelbi mbetet i njëjtë - mund të jetoni në një botë të plotë të koherencës.
Megjithatë, le të kthehemi te detyra e fillimit. Nëse një pjesë e sistemit mund të ndërtohet me , atëherë mund të ndërtohet skema e mëposhtme.

Veçoritë e rëndësishme të kësaj qasje janë:
- Çdo kërkesë e ardhshme vihet në një radhë.
- Gjatë procesit të përpunimit të kërkesës, shërbimi gjithashtu mund të vendosë detyra në radhë të tjera.
- Çdo ngjarje e ardhshme ka një identifikues (i nevojshëm për deduplifikimin).
- Radhë ideologjike funksionon sipas skemës "append only". Elementët nuk mund të hiqen apo të riorganizohen nga kjo.
- Radhë funksionon sipas skemës FIFO (na falni për tautologjinë). Nëse është e nevojshme të bëhet ekzekutimi paralel, duhet të riorganizoni objektet në radhë të ndryshme në një nga hapat.
Më kujtohet se ne po shqyrtojmë rastin e një depo online. Në këtë rast, sistemi do të duket përafërsisht kështu:

Është e rëndësishme që shërbimet në diagram nuk do të thotë domosdoshmërisht një server të veçantë. Edhe procesi mund të jetë i njëjtë. Ajo që është e rëndësishme është: ideologjikisht këto gjëra janë të ndara në një mënyrë që mund të aplikohet lehtësisht shkallëzimi horizontal.
Dhe për dy përdorues, skema do të dukej kështu (shërbimet e destinuara për përdorues të ndryshëm, janë të shënuara me ngjyra të ndryshme):

Bonusët nga një kombinim i tillë:
- Shërbimet e përpunimit të informacionit janë të ndara. Radhët gjithashtu janë të ndara. Nëse duhet të rrisim kapacitetin e sistemit, ne thjesht duhet të aktivizojmë më shumë shërbime në një numër më të madh serverësh.
- Kur marrim informacion nga përdoruesi, nuk është e nevojshme të presim ruajtjen e plotë të të dhënave. Përkundrazi, mjafton të përgjigjemi "ok", dhe pastaj të fillojmë punën gradualisht. Radhë gjithashtu zbut kulmin, sepse shtimi i një objekti të ri ndodh shpejt, dhe përdoruesi nuk duhet të presë për kalimin e plotë në gjithë ciklin.
- Si një shembull, unë kam shtuar shërbimin e deduplifikimit, i cili përpiqet të bashkojë skedarë të njëjtë. Nëse punon ngadalë në 1% të rasteve, klienti këtë praktikisht nuk do ta vërenë (shih më sipër), që është një avantazh i madh, sepse nuk na nevojitet shpejtësia dhe besueshmëria e 100% nga ne.
Megjithatë, menjëherë duken edhe disavantazhet:
- Sistemi ynë ka humbur koherencën strikte. Kjo do të thotë se nëse, për shembull, abonoheni në shërbime të ndryshme, teorikisht mund të merrni një gjendje të ndryshme (sepse një nga shërbimet mund të mos arrijë të marrë njoftimin nga radhën e brendshme). Si një pasojë tjetër, sistemi tani nuk ka një kohë të përbashkët. Kështu që nuk mund të renditni të gjitha ngjarjet thjesht sipas kohës së mbërritjes, sepse orët midis serverëve mund të mos jenë sinkronike (madje, e njëjta kohë në dy serverë është një utopi).
- Asnjë ngjarje nuk mund të kthjellohet tani thjesht (siç do të mund të bënte me një bazë të dhënash). Në vend të kësaj, është e nevojshme të shtoni një ngjarje të re - , e cila do të ndryshojë gjendjen e fundit në atë të nevojshme. Si një shembull nga një fushë e ngjashme: pa riparimin e historisë (çka është e keqe në disa raste) në git nuk mund të kthjelloni një komit, megjithatë mund të bëni një , i cili në thelb do të sjellë gjendjen e vjetër. Megjithatë, në histori do të ruhet si komiti i gabuar edhe komiti i kthimit.
- Skema e të dhënave mund të ndryshojë nga një version në tjetrin, por tani nuk është e mundur që ngjarjet e vjetra të përditësohen në standardin e ri (sepse në parim ngjarjet nuk mund të ndryshojnë).
Siç duket, Event Sourcing funksionon shkëlqyer me CQRS. Më shumë, realizimi i një sistemi me radhë efektive dhe të përshtatshme, përkundër mungesës së ndarjes së kanaleve të të dhënave, tashmë është vetë një sfidë, sepse do të duhet të shtohen pika sinkronizimi që do të neutralizojnë të gjithë efektin pozitiv të radhëve. Rreth të dyja qasjeve duke e përdorur atë, është e nevojshme të bëhet një korrigjim i vogël në kodin e punës së programit. Në rastin tonë, kur dërgojmë një skedë në server, në përgjigje merrim vetëm ‘ok’, që do të thotë se ‘operacioni i shtimit të skedës është ruajtur’. Formalisht, kjo nuk do të thotë se të dhënat janë tashmë të disponueshme në pajisje të tjera (për shembull, shërbimi i dedupikimit mund të rikonstruktojë indeksin). Megjithatë, pas një kohë, klienti do të marrë një njoftim në stilin ‘skeda X është ruajtur’.
Si rezultat:
- Numri i qëndrimeve të dërgimit të skedave po rritet: përveç ‘skeda është dërguar’, tani kemi dy: ‘skeda është shtuar në radhë në server’ dhe ‘skeda është ruajtur në ruajtje’. E dyta do të thotë se pajisjet e tjera tashmë mund të fillojnë të marrin skedën (me rezervimin se radhët funksionojnë me shpejtësi të ndryshme).
- Për shkak se informacioni mbi dërgimin tani vjen përmes kanaleve të ndryshme, na nevojitet të dizajnojmë zgjidhje për të marrë statusin e përpunimit të skedës. Si pasojë e kësaj: ndryshe nga kërkesa-klienti klasik, klienti mund të rindezë gjatë përpunimit të skedës, mirëpo statusi i këtij përpunimi do të jetë i saktë. Dhe ky pikë funksionon, në parim, ‘nga kutia’. Si pasojë: tani jemi më tolerantë ndaj dështimeve.
Sharding
Siç është përmendur më lart, në sistemet me event sourcing nuk ka një koherencë të fortë. Kështu që mund të përdorim disa ruajtje pa ndonjë sinkronizim midis tyre. Duke iu afruar detyrës sonë, ne mundemi:
- Të ndajmë skedat sipas llojeve. Për shembull, imazhet/videot mund të dekodohen dhe të zgjidhet një format më efikas.
- Të ndajmë llogaritë sipas vendeve. Për shkak të shumë ligjeve, kjo mund të kërkohet, megjithatë, kjo skemë arkitekturale e ofron këtë mundësi automatikisht.

Nëse dëshironi të transferoni të dhëna nga një ruajtje në tjetrën, atëherë këtu nuk do të jetë e mundur me mjete standarde. Fatkeqësisht, në një rast të tillë duhet të ndaloni radhen, të kryeni migrimin dhe pastaj të rinisni atë. Në rastin më të përgjithshëm, të dhënat nuk mund të transferohen ‘në flakë’, por, nëse radhët e ngjarjeve ruhen plotësisht dhe ju keni kopje të gjendjeve të mëparshme të ruajtjes, mund të riprodhoni ngjarjet në këtë mënyrë:
- Në Event Source, çdo ngjarje ka identifikuesin e saj (idealisht — jo në rritje). Kështu që në ruajtje mund të shtojmë një fushë — id e elementit të fundit të përpunuar.
- Duplicojmë radhen, në mënyrë që të gjitha ngjarjet të mund të përpunohen për disa ruajtje të pavarura (e para — është ajo në të cilën tashmë ruhen të dhënat, dhe e dyta — e re, por për momentin e zbrazët). Radha e dytë, natyrisht, për momentin nuk po përpunon.
- Nisemi me radhen e dytë (domethënë, fillojmë riprodhimin e ngjarjeve).
- Kur radha e re të jetë relativisht e zbrazët (dmth. diferenca mes mesatares së kohës që kalon nga shtimi i një elementi dhe nxjerrja e tij është e pranueshme), mund të fillojmë të kalojmë lexuesit në ruajtjen e re.
Siç duket, në sistemin tonë asnjëherë nuk ka qenë dhe nuk ka koherencë të fortë. Ka vetëm eventual consistency, domethënë një garanci se ngjarjet përpunohen në rendin e njëjtë (megjithatë, ndoshta me vonesa të ndryshme). Dhe, duke e shfrytëzuar këtë, ne mund të transferojmë të dhënat relativisht lehtë pa ndalur sistemin në anën tjetër të globit.
Kështu, duke vazhduar me shembujt tanë për ruajtjen online të skedave, një arkitekturë e tillë tashmë na ofron disa avantazhe:
- Ne mund të lëvizim objektet më afër përdoruesve, duke bërë këtë në mënyrë dinamike. Kështu mund të përmirësojmë cilësinë e shërbimit.
- Ne mund të ruajmë një pjesë të të dhënave brenda kompanive. Për shembull, përdoruesit e Enterprise shpesh kërkojnë që të dhënat e tyre të ruhen në qendra të kontrolluara (për të shmangur rrjedhjen e të dhënave). Falë sharding, ne mund ta mbështesim këtë pa ndonjë problem. Dhe detyra bëhet edhe më e lehtë nëse klienti ka një cloud kompatibil. ).
- Dhe gjëja më e rëndësishme është se ne mund ta bëjmë këtë pa qenë të detyruar. Në fakt, për fillim, na mjafton një depo për të gjitha llogaritë (për të filluar më shpejt). Tipari kyç i kësaj sistemi është se, ndonëse është i zgjerueshëm, në fazën fillestare është mjaft i thjeshtë. Thjesht, nuk duhen shkruar menjëherë kodet që punojnë me miliona kuota të pavarura etj. Nëse nevojitet, kjo mund të bëhet në të ardhmen.
Static Content Hosting
Ky pikë mund të duket krejtësisht e qartë, megjithatë është ende e nevojshme për një aplikacion të ngarkuar më shumë ose më pak standard. Qëllimi i tij është i thjeshtë: i gjithë përmbajtja statike shpërndahet jo nga serveri ku ndodhet aplikacioni, por nga serverë të veçantë, të dedikuar saktësisht për këtë punë. Si pasojë, këto operacione kryhen më shpejt (një nginx i zakonshëm dorëzon skedarët më shpejt dhe më lirë se një server Java). Për më tepër, arhitektura e CDN () lejon që skedarët tanë të jenë më afër përdoruesve të fundit, që ndikon pozitivisht në komoditetin e punës me shërbimin.
Shembulli më i thjeshtë dhe standard i përmbajtjes statike është një grup skriptesh dhe imazhesh për një faqe. Me to është e thjeshtë — ato janë të njohura paraprakisht, më pas arkivi ngarkohet në serverat e CDN, nga ku shpërndahen për përdoruesit e fundit.
Megjithatë, në realitet, për përmbajtjen statike mund të aplikohet një qasje që është paksa e ngjashme me arkitekturën lambda. Le të kthehemi në detyrën tonë (depo online skedaresh), ku na nevojitet të shpërndajmë skedarët për përdoruesit. Zgjidhja më e thjeshtë do të ishte të bënim një shërbim, i cili për çdo kërkesë të përdoruesit bën të gjitha verifikimet e nevojshme (autorizimi etj.) dhe më pas shkarkon skedarin direkt nga depoja jonë. Mangësia kryesore e një qasje të tillë është se përmbajtja statike (dhe një skedar me një revizion të caktuar, për thelb, është përmbajtje statike) shpërndahet nga i njëjti server që mban logjikën e biznesit. Në vend të kësaj, mund të kemi këtë skemë:
- Serveri jep një URL për shkarkimin. Ajo mund të ketë formën file_id + key, ku key është një nënshkrim dixhital i vogël, që jep të drejtë për akses në burimin për një ditë të afërt.
- Shpërndarja e skedarëve merret nga një nginx i thjeshtë me opsionet e mëposhtme:
- Kështu, si ky shërbim mund të jetë në një server të veçantë, ne kemi lënë vetes hapësirë për në të ardhmen me mundësinë për të ruajtur të gjitha skedarët e fundit të shkarkuar në disk.
- Verifikimi i çelësit në momentin e krijimit të lidhjes
- Opsionale: përpunimi i përmbajtjes në rrjedhë. Për shembull, nëse kompresojmë të gjithë skedarët në shërbim, mund të bëjmë dekompresimin direkt në këtë modul. Si pasojë: operacionet IO bëhen aty ku kanë më shumë vend. Një arkivues në Java do të jetë në gjendje të ndajë shumë memorje të tepërt, megjithatë, rishkrimi i shërbimit me logjikën e biznesit në Rust/C++ do të dukej gjithashtu joefikas. Në rastin tonë, përdoren procese të ndryshme (ose madje shërbime), prandaj mund të ndajmë mjaft efektivisht logjikën e biznesit nga operacionet IO.

Një skemë e tillë nuk duket shumë si shpërndarja e përmbajtjes statike (sepse ne nuk po ngarkojmë gjithë paketën e statikës diku), megjithatë, në realitet, kjo qasje merret me shpërndarjen e të dhënave të pandryshueshme. Për më tepër, kjo skemë mund të përgjithësohet për raste të tjera, kur përmbajtja nuk është vetëm statike, por mund të paraqitet si një grup blokesh të pandryshueshme dhe të padishtë (pavarësisht se ato mund të shtohen).
Si një shembull tjetër (për konfirmim): nëse keni punuar me Jenkins/TeamCity, e dini që të dyja zgjidhjet janë të shkruara në Java. Të dy përfaqësojnë një proces Java, i cili merret me orkestrimin e ndërtimeve dhe menaxhimin e përmbajtjes. Në veçanti, të dy kanë detyra si "të dërgojnë një skedar/fond nga serveri". Si shembull: dorëzimi i artefakteve, transmetimi i kodit burimor (kur agjenti nuk e shkarkon kodin direkt nga repozitori, por serveri e bën këtë), akses në logjet. Të gjitha këto detyra ndryshojnë në ngarkesën e IO. Do të thotë, se serveri, i cili është përgjegjës për logjikën komplekse të biznesit, gjithashtu duhet të jetë në gjendje të shtyjë në mënyrë efektive flukse të mëdha të dhënash. Dhe ajo që është më e interesantja, një operacion të tillë mund të delegohet po ashtu nginx-it sipas të njëjtës skemë (përveçse në kërkesë duhet të shtohet çelësi i të dhënave).
Megjithatë, për të kthyer në sistemin tonë, del një skemë e tillë:

Siç duket, sistemi është komplikuar ndjeshëm. Tani nuk është thjesht një mini-proces që ruan skedarët lokalisht. Tani nevojitet një mbështetje jo e thjeshtë, kontrolli i versioneve të API-së etj. Prandaj, pasi të gjitha diagramet të jenë vizatuar, është më e mira të vlerësohet në detaje nëse ia vlen zgjerimi i kostove të tilla. Megjithatë, nëse dëshironi të keni mundësi zgjerimi të sistemit (përfshirë në punën me një numër të madh përdoruesish), do të duhet të pranoni zgjidhje të tilla. Por si rezultat, sistemi është arkitekturërisht i gatshëm për rritjen e ngarkesës (praktikisht çdo komponent mund të klonohet për skalim horizontal). Sistemi mund të përmirësohet pa u ndalur (thjesht disa operacione do të ngadalësohen paksa).
Siç e thashë që në fillim, tani një sërë shërbimesh interneti ka filluar të përballet me ngarkesa në rritje. Dhe disa prej tyre thjesht kanë filluar të ndalojnë së funksionuari siç duhet. Në thelb, sistemet dështuan pikërisht në momentin kur biznesi duhet të bënte para. Domethënë, në vend të dorëzimit të vonuar, në vend të ofrimit të klientëve 'planifikoni dorëzimin për muajt e ardhshëm', sistemi thjesht tha 'shkoni te konkurentët'. Kjo është çmimi i performancës të ulët: humbjet ndodhin pikërisht në atë moment kur fitimi do të ishte më i lartë.
Përfundimi
Të gjithë këto qasje ishin të njohura më parë. Po ashtu VK ka përdorur prej kohësh idenë e Static Content Hosting për të shpërndarë imazhe. Një sërë lojërash online përdorin skemën e Sharding për ndarjen e lojtarëve sipas rajoneve ose për ndarjen e lokacioneve të lojës (nëse bota vetë është e njëjtë). Qasja Event Sourcing përdoret gjerësisht në postën elektronike. Shumica e aplikacioneve të tregtarëve, ku të dhënat vijnë vazhdimisht, janë në të vërtetë të ndërtuara sipas qasjes CQRS, për të pasur mundësi të filtrohen të dhënat e marra. Po ashtu, skalimi horizontal është aplikuar prej kohësh në shumë shërbime.
Megjithatë, ajo që është më e rëndësishme, të gjithë këto modele janë bërë shumë të lehta për t'u aplikuar në aplikacionet moderne (nëse janë të vendosura siç duhet, natyrisht). Reformat ofrojnë Sharding dhe skalim horizontal menjëherë, gjë që është shumë më e lehtë sesa të porositni servera të dedikuar në qendra të ndryshme të të dhënave vetë. CQRS është bërë shumë më e lehtë, të paktën për shkak të zhvillimit të librarive si RX. Dhjetë vjet më parë, një faqe web-i e zakonshme do të ishte e përballueshme ta mbështeste këtë. Event Sourcing gjithashtu konfigurohet jashtëzakonisht lehtë falë konteinerëve të gatshëm me Apache Kafka. Dhjetë vjet më parë kjo do të ishte një novacion, tani është diçka e zakonshme. Njësoj ndodh edhe me Static Content Hosting: për shkak të teknologjive më të përshtatshme (duke përfshirë edhe dokumentacionin e detajuar dhe një bazë të madhe për përgjigje), qasja ka bërë akoma më të lehtë.
Si përfundim, implementimi i disa modele të ndërlikuara arkitekturore tani është bërë shumë më i lehtë, prandaj është më mirë t'i kushtojmë vëmendje që në fillim. Nëse në një aplikacion një dekadë më parë u hoq një nga zgjidhjet e mësipërme për shkak të kostove të larta të implementimit dhe mirëmbajtjes, tani, në aplikacionin e ri, ose pas një refaktorizimi, mund të ndërtohet një shërbim që arkitekturally do të jetë si i zgjerueshëm (nga perspektiva e performancës), ashtu dhe i gatshëm për kërkesat e reja nga klientët (p.sh., për lokalizimin e të dhënave personale).
Dhe më e rëndësishmja: ju lutemi, mos i përdorni këto qasje nëse keni një aplikacion të thjeshtë. Po, ato janë të bukura dhe interesante, megjithatë për një faqe të vizitës maksimale prej 100 njerëzish shpesh mund të mjaftohemi me një monolit klasik (të paktën nga jashtë, brenda gjithçka mund të ndahet në modulet etj.).
Burimi: habr.com
