{"id":80035,"date":"2020-05-02T13:42:54","date_gmt":"2020-05-02T11:42:54","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny"},"modified":"2020-05-02T13:42:54","modified_gmt":"2020-05-02T11:42:54","slug":"udobnye-arhitekturnye-patterny","status":"publish","type":"post","link":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","title":{"rendered":"Modele arhitecturale convenabile","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Salut, Habr!<\/p>\n<p><\/p>\n<p>\u00cen lumina evenimentelor curente cauzate de coronavirus, o serie de servicii internet au \u00eenceput s\u0103 primeasc\u0103 o \u00eenc\u0103rc\u0103tur\u0103 crescut\u0103. De exemplu, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.independent.co.uk\/life-style\/gadgets-and-tech\/news\/coronavirus-ocado-down-app-website-stockpiling-food-online-delivery-a9402216.html\">una dintre re\u021belele de retail din Regatul Unit a oprit pur \u0219i simplu site-ul cu comenzi online<\/a><\/noindex>, deoarece nu erau suficiente resurse. \u0218i de cele mai multe ori nu po\u021bi accelera un server doar prin ad\u0103ugarea de hardware mai puternic, \u00eens\u0103 trebuie s\u0103 gestionezi cererile clien\u021bilor (sau ace\u0219tia vor merge la concuren\u021b\u0103).<\/p>\n<p><\/p>\n<p>\u00cen acest articol, voi prezenta pe scurt practici populare care vor permite crearea unui serviciu rapid \u0219i rezistent la erori. Totu\u0219i, din schemele posibile de dezvoltare, am selectat doar acele metode <strong>u\u0219or de utilizat<\/strong>. Pentru fiecare punct, ave\u021bi fie biblioteci gata preg\u0103tite, fie solu\u021bii disponibile prin platforme cloud.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"gorizontalnoe-masshtabirovanie\">Scalare orizontal\u0103<\/h1>\n<p><\/p>\n<p>Cel mai simplu \u0219i cunoscut punct. Schematic, cele dou\u0103 metode cele mai frecvente de distribuire a sarcinii sunt scalarea orizontal\u0103 \u0219i vertical\u0103. <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9C%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D1%81%D1%82%D1%8C#%D0%93%D0%BE%D1%80%D0%B8%D0%B7%D0%BE%D0%BD%D1%82%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BC%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5\">\u00cen primul caz,<\/a><\/noindex> permi\u021bi serviciilor s\u0103 func\u021bioneze \u00een paralel, distribuind astfel sarcina \u00eentre ele. <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9C%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D1%83%D0%B5%D0%BC%D0%BE%D1%81%D1%82%D1%8C#%D0%92%D0%B5%D1%80%D1%82%D0%B8%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BC%D0%B0%D1%81%D1%88%D1%82%D0%B0%D0%B1%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5\">\u00cen al doilea caz,<\/a><\/noindex> comanzi servere mai puternice sau \u00ee\u021bi optimizezi codul.<\/p>\n<p><\/p>\n<p>Pentru exemplu, voi lua un spa\u021biu de stocare \u00een cloud abstract, adic\u0103 un analog al OwnCloud, OneDrive etc.<\/p>\n<p><\/p>\n<p>Imaginea standard a unei astfel de scheme este prezentat\u0103 mai jos, dar aceasta demonstreaz\u0103 doar complexitatea sistemului. Trebuie s\u0103 g\u0103sim o modalitate de a sincroniza serviciile. Ce se \u00eent\u00e2mpl\u0103 dac\u0103 un utilizator salveaz\u0103 un fi\u0219ier de pe tablet\u0103 \u0219i apoi vrea s\u0103-l vizualizeze pe telefon?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Modele arhitecturale convenabile\" src=\"\/wp-content\/uploads\/2020\/05\/7512c6d8783f5e0a38cc0861b01e54c8.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDiferen\u021ba dintre abord\u0103ri: \u00een scalarea vertical\u0103 suntem preg\u0103ti\u021bi s\u0103 cre\u0219tem puterea nodurilor, iar \u00een scalarea orizontal\u0103 \u2013 s\u0103 ad\u0103ug\u0103m noduri noi pentru a distribui sarcina.<\/p>\n<p><\/p>\n<h1 id=\"cqrs\">CQRS<\/h1>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/martinfowler.com\/bliki\/CQRS.html\">Command Query Responsibility Segregation<\/a><\/noindex> este un tipar destul de important, deoarece permite diferitelor clien\u021bi s\u0103 se conecteze nu doar la servicii diferite, ci \u0219i s\u0103 primeasc\u0103 fluxuri de evenimente identice. Beneficiile sale nu sunt at\u00e2t de evidente pentru o aplica\u021bie simpl\u0103, totu\u0219i, este extrem de important (\u0219i simplu) pentru un serviciu saturat. Conceptul s\u0103u: fluxurile de date de intrare \u0219i ie\u0219ire nu trebuie s\u0103 se intersece. Aceasta \u00eenseamn\u0103 c\u0103 nu po\u021bi trimite o cerere \u0219i a\u0219tepta un r\u0103spuns, \u00een schimb trimite\u021bi o cerere la serviciul A, dar prime\u0219ti un r\u0103spuns la serviciul B.<\/p>\n<p><\/p>\n<p>Primul avantaj al acestei abord\u0103ri este capacitatea de a \u00eentrerupe conexiunea (\u00een sens larg) \u00een timpul execut\u0103rii unei cereri de lung\u0103 durat\u0103. Ca exemplu, s\u0103 lu\u0103m o secven\u021b\u0103 mai mult sau mai pu\u021bin standard:<\/p>\n<p><\/p>\n<ol>\n<li>Clientul a trimis o cerere serverului.<\/li>\n<li>Serverul a \u00eenceput prelucrarea \u00eendelungat\u0103.<\/li>\n<li>Serverul a r\u0103spuns clientului cu rezultatul.<\/li>\n<\/ol>\n<p><\/p>\n<p>S\u0103 presupunem c\u0103 la punctul 2 a avut loc o \u00eentrerupere a conexiunii (sau re\u021beaua s-a reconectat, sau utilizatorul a navigat pe o alt\u0103 pagin\u0103, \u00eentrerup\u00e2nd conexiunea). \u00cen acest caz, serverului \u00eei va fi greu s\u0103 trimit\u0103 r\u0103spunsul utilizatorului cu informa\u021bii despre ce a fost procesat. Aplic\u00e2nd CQRS, secven\u021ba va fi pu\u021bin diferit\u0103:<\/p>\n<p><\/p>\n<ol>\n<li>Clientul s-a abonat la actualiz\u0103ri.<\/li>\n<li>Clientul a trimis o cerere serverului.<\/li>\n<li>Serverul a r\u0103spuns \u201ecerere acceptat\u0103\u201d.<\/li>\n<li>Serverul a trimis rezultatul prin canalul din punctul \u201e1\u201d.<\/li>\n<\/ol>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Modele arhitecturale convenabile\" src=\"\/wp-content\/uploads\/2020\/05\/8a00ea93eecc7cc0754122857c5f90d0.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dup\u0103 cum se poate observa, schema este pu\u021bin mai complex\u0103. Mai mult, abordarea intuitiv\u0103 request-response lipse\u0219te aici. Cu toate acestea, dup\u0103 cum se poate observa, o \u00eentrerupere a conexiunii \u00een timpul proces\u0103rii cererii nu va duce la o eroare. Mai mult, dac\u0103 utilizatorul este \u00eentr-adev\u0103r conectat la serviciu de pe mai multe dispozitive (de exemplu, de pe telefonul mobil \u0219i de pe tablet\u0103), r\u0103spunsul poate fi trimis pe ambele dispozitive.<\/p>\n<p><\/p>\n<p>Ce este interesant, este c\u0103 codul de prelucrare a mesajelor de intrare devine similar (nu 100%) at\u00e2t pentru evenimentele afectate de client, c\u00e2t \u0219i pentru celelalte evenimente, inclusiv cele de la al\u021bi clien\u021bi.<\/p>\n<p><\/p>\n<p>Cu toate acestea, \u00een realitate ob\u021binem bonusuri suplimentare datorit\u0103 faptului c\u0103 fluxul unidirec\u021bional poate fi procesat \u00een stil func\u021bional (folosind RX \u0219i analogii). Aceasta este o mare realizare, deoarece, \u00een esen\u021b\u0103, aplica\u021bia poate deveni complet reactiv\u0103, cu aplicarea abord\u0103rii func\u021bionale. Pentru aplica\u021biile complexe, aceasta poate economisi semnificativ resurse \u00een dezvoltare \u0219i \u00eentre\u021binere.<\/p>\n<p><\/p>\n<p>Dac\u0103 combin\u0103m aceast\u0103 abordare cu scalarea orizontal\u0103, atunci ca bonus ob\u021binem capacitatea de a trimite cereri la un server, dar a primi r\u0103spunsuri de la altul. Astfel, clientul poate alege serviciul care \u00eei este convenabil, iar sistemul intern va putea totu\u0219i s\u0103 proceseze corect evenimentele.<\/p>\n<p><\/p>\n<h1 id=\"event-sourcing\">Event Sourcing<\/h1>\n<p><\/p>\n<p>Dup\u0103 cum \u0219ti\u021bi, una dintre caracteristicile principale ale unui sistem distribuit este lipsa unui timp comun \u0219i a unei sec\u021biuni critice comune. Pentru un singur proces, pute\u021bi realiza sincronizarea (pe acelea\u0219i mutexuri), \u00een care sunte\u021bi sigur c\u0103 nimeni altcineva nu execut\u0103 acest cod. Totu\u0219i, pentru un sistem distribuit, aceasta este periculoas\u0103, deoarece va necesita overhead, iar toat\u0103 frumuse\u021bea scalabilit\u0103\u021bii va fi anulat\u0103 \u2014 \u00een orice caz, toate componentele vor a\u0219tepta una.<\/p>\n<p><\/p>\n<p>A\u0219adar, ajungem la un fapt important \u2014 un sistem distribuit rapid nu poate fi sincronizat, deoarece ne va reduce performan\u021ba. Pe de alt\u0103 parte, de multe ori avem nevoie de o anumit\u0103 coeren\u021b\u0103 a componentelor. \u0218i pentru asta putem folosi abordarea cu <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">consisten\u021b\u0103 eventual\u0103<\/a><\/noindex>, unde se garanteaz\u0103 c\u0103, \u00een absen\u021ba modific\u0103rilor datelor, dup\u0103 un anumit interval de timp de la ultima actualizare (\u201e\u00een cele din urm\u0103\u201d), toate solicit\u0103rile vor returna ultima valoare actualizat\u0103.<\/p>\n<p><\/p>\n<p>Este important s\u0103 \u00een\u021belegem c\u0103 pentru bazele de date clasice se aplic\u0103 destul de des <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Consistency_model#Strict_consistency\">coeren\u021ba strict\u0103<\/a><\/noindex>, unde fiecare nod de\u021binea aceea\u0219i informa\u021bie (acest lucru se ob\u021bine de obicei atunci c\u00e2nd tranzac\u021bia este considerat\u0103 stabilit\u0103 doar dup\u0103 ce prime\u0219te un r\u0103spuns de la al doilea server). Aici exist\u0103 anumite relax\u0103ri din cauza nivelurilor de izolare, totu\u0219i esen\u021ba general\u0103 r\u0103m\u00e2ne aceea\u0219i \u2014 pute\u021bi tr\u0103i \u00eentr-o lume complet coerent\u0103.<\/p>\n<p><\/p>\n<p>Dar s\u0103 ne \u00eentoarcem la problema ini\u021bial\u0103. Dac\u0103 o parte a sistemului poate fi construit\u0103 cu <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">consisten\u021b\u0103 eventual\u0103<\/a><\/noindex>, atunci se poate construi urm\u0103toarea schem\u0103.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Modele arhitecturale convenabile\" src=\"\/wp-content\/uploads\/2020\/05\/33c80be6bc33bd897ca9b9e5525f9ae8.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Caracteristicile importante ale acestei abord\u0103ri:<\/p>\n<p><\/p>\n<ul>\n<li>Fiecare solicitare primit\u0103 este plasat\u0103 \u00eentr-o coad\u0103.<\/li>\n<li>\u00cen procesul de procesare a solicit\u0103rii, serviciul poate, de asemenea, s\u0103 plaseze sarcini \u00een alte cozi.<\/li>\n<li>Fiecare eveniment primit are un identificator (care este necesar pentru deduplicare).<\/li>\n<li>Coada func\u021bioneaz\u0103 ideologic pe baza schemei &quot;append only&quot;. Nu se pot elimina elemente sau reordona.<\/li>\n<li>Coad\u0103 func\u021bioneaz\u0103 pe principiul FIFO (\u00eemi pare r\u0103u pentru tautologie). Dac\u0103 este necesar\u0103 executarea paralel\u0103, atunci trebuie s\u0103 rearanja\u021bi obiectele \u00een diferite cozi \u00een unul dintre etape.<\/li>\n<\/ul>\n<p><\/p>\n<p>\u00cemi amintesc c\u0103 discut\u0103m despre cazul unui stocare online a fi\u0219ierelor. \u00cen acest caz, sistemul va ar\u0103ta, aproximativ, astfel:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Modele arhitecturale convenabile\" src=\"\/wp-content\/uploads\/2020\/05\/b95efb29545dcde1db9432d12d00a1b1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Este important de \u0219tiut c\u0103 serviciile din diagram\u0103 nu semnific\u0103 neap\u0103rat un server separat. Chiar dac\u0103 procesul poate fi acela\u0219i. Ce este esen\u021bial este c\u0103, ideologic, aceste lucruri sunt separate astfel \u00eenc\u00e2t s\u0103 permit\u0103 o scalare orizontal\u0103 u\u0219oar\u0103.<\/p>\n<p><\/p>\n<p>Iar pentru doi utilizatori, schema va ar\u0103ta astfel (serviciile destinate diferitelor utilizatori sunt marcate cu culori diferite):<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Modele arhitecturale convenabile\" src=\"\/wp-content\/uploads\/2020\/05\/4c4aadc8b9dd505c3ad743e69fee4fae.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Beneficiile unei astfel de combina\u021bii:<\/p>\n<p><\/p>\n<ul>\n<li>Serviciile pentru procesarea informa\u021biilor sunt separate. Cozile sunt, de asemenea, separate. Dac\u0103 va fi necesar s\u0103 cre\u0219tem capacitatea de procesare a sistemului, tot ce trebuie s\u0103 facem este s\u0103 lans\u0103m mai multe servicii pe un num\u0103r mai mare de servere.<\/li>\n<li>C\u00e2nd primim informa\u021bii de la utilizator, nu trebuie neap\u0103rat s\u0103 a\u0219tept\u0103m finalizarea complet\u0103 a salv\u0103rii datelor. Dimpotriv\u0103, este suficient s\u0103 r\u0103spundem \u201eok\u201d, iar apoi s\u0103 \u00eencepem s\u0103 lucr\u0103m treptat. De asemenea, coada atenueaz\u0103 v\u00e2rfurile, deoarece ad\u0103ugarea unui nou obiect se face rapid, iar utilizatorul nu trebuie s\u0103 a\u0219tepte \u00eentregul ciclu.<\/li>\n<li>Ca exemplu, am ad\u0103ugat un serviciu de deduplicare, care \u00eencearc\u0103 s\u0103 uneasc\u0103 fi\u0219ierele identice. Dac\u0103 acesta func\u021bioneaz\u0103 mult timp \u00een 1% din cazuri, clientul aproape c\u0103 nu va observa (vezi mai sus), ceea ce este un mare avantaj, deoarece nu mai este necesar\u0103 o vitez\u0103 \u0219i o fiabilitate de 100%.<\/li>\n<\/ul>\n<p><\/p>\n<p>Cu toate acestea, se pot observa \u0219i dezavantajele:<\/p>\n<p><\/p>\n<ul>\n<li>Sistemul nostru a pierdut coeren\u021ba strict\u0103. Asta \u00eenseamn\u0103 c\u0103, de exemplu, dac\u0103 ne abon\u0103m la servicii diferite, teoretic putem ob\u021bine st\u0103ri diferite (deoarece unul dintre servicii poate s\u0103 nu reu\u0219easc\u0103 s\u0103 primeasc\u0103 notificarea din coada intern\u0103). Ca un alt efect, sistemul nu mai are un timp comun. Asta \u00eenseamn\u0103 c\u0103 nu putem, de exemplu, s\u0103 sort\u0103m toate evenimentele pur \u0219i simplu dup\u0103 timpul de sosire, deoarece ceasurile dintre servere pot s\u0103 nu fie sincronizate (mai mult, a avea aceea\u0219i or\u0103 pe dou\u0103 servere este o utopie).<\/li>\n<li>Niciun eveniment nu poate fi acum pur \u0219i simplu inversat (a\u0219a cum s-ar putea face cu o baz\u0103 de date). \u00cen schimb, este necesar s\u0103 ad\u0103ug\u0103m un nou eveniment \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/49451237\/compensating-events-on-cqrs-es-architecture\">compensation event<\/a><\/noindex>, care va schimba ultima stare \u00een cea necesar\u0103. Ca exemplu dintr-o zon\u0103 similar\u0103: f\u0103r\u0103 re\u00eenscrierea istoricului (ceea ce este r\u0103u \u00een unele cazuri) \u00een git nu se poate inversa un commit, \u00eens\u0103 se poate realiza un <noindex><a rel=\"nofollow\" href=\"https:\/\/git-scm.com\/docs\/git-revert\">rollback commit<\/a><\/noindex>, care de fapt va returna pur \u0219i simplu starea anterioar\u0103. Totu\u0219i, istoricul va p\u0103stra at\u00e2t commit-ul gre\u0219it, c\u00e2t \u0219i rollback-ul.<\/li>\n<li>Schema de date se poate schimba de la o versiune la alta, totu\u0219i evenimentele vechi nu pot fi actualizate la noul standard (deoarece, \u00een principiu, evenimentele nu pot fi modificate).<\/li>\n<\/ul>\n<p><\/p>\n<p>Dup\u0103 cum se poate observa, Event Sourcing se integreaz\u0103 excelent cu CQRS. Mai mult, implementarea unui sistem cu cozi eficiente \u0219i confortabile, dar f\u0103r\u0103 separarea fluxurilor de date, este deja de la sine complicat\u0103, deoarece va trebui s\u0103 ad\u0103ug\u0103m puncte de sincronizare care vor anula \u00eentregul efect pozitiv al cozilor. Aplic\u00e2nd ambele abord\u0103ri simultan, este necesar\u0103 o mic\u0103 ajustare a codului func\u021bion\u0103rii programei. \u00cen cazul nostru, c\u00e2nd trimitem un fi\u0219ier pe server, r\u0103spunsul returnat este doar \u201cok\u201d, ceea ce \u00eenseamn\u0103 doar c\u0103 \u201copera\u021biunea de ad\u0103ugare a fi\u0219ierului a fost salvat\u0103\u201d. Formal, aceasta nu \u00eenseamn\u0103 c\u0103 datele sunt deja disponibile pe alte dispozitive (de exemplu, serviciul de deduplicare poate reconstrui indexul). Totu\u0219i, dup\u0103 un timp, clientul va primi o notificare de tip \u201cfi\u0219ierul X a fost salvat\u201d.<\/p>\n<p><\/p>\n<p>Ca rezultat:<\/p>\n<p><\/p>\n<ul>\n<li>Num\u0103rul statutelor de trimitere a fi\u0219ierelor cre\u0219te: \u00een loc de clasicul \u201cfi\u0219ier trimis\u201d, ob\u021binem dou\u0103: \u201cfi\u0219ier ad\u0103ugat \u00een coada serverului\u201d \u0219i \u201cfi\u0219ier salvat \u00een stocare\u201d. Ultimul \u00eenseamn\u0103 c\u0103 alte dispozitive pot \u00eencepe deja s\u0103 primeasc\u0103 fi\u0219ierul (cu observa\u021bia c\u0103 cozile func\u021bioneaz\u0103 cu viteze diferite).<\/li>\n<li>Din cauza faptului c\u0103 informa\u021biile despre trimitere vin acum prin diferite canale, trebuie s\u0103 g\u0103sim solu\u021bii pentru a ob\u021bine statutul prelucr\u0103rii fi\u0219ierului. Drept urmare: spre deosebire de clasicul request-response, clientul poate fi repornit \u00een timpul prelucr\u0103rii fi\u0219ierului, totu\u0219i statutul acestei prelucr\u0103ri va fi corect. De fapt, acest punct func\u021bioneaz\u0103, \u00een esen\u021b\u0103, din cutie. Ca urmare: suntem acum mai toleran\u021bi la erori.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sharding\">Sharding<\/h1>\n<p><\/p>\n<p>Dup\u0103 cum s-a men\u021bionat mai sus, \u00een sistemele cu event sourcing nu exist\u0103 o consisten\u021b\u0103 strict\u0103. Asta \u00eenseamn\u0103 c\u0103 putem folosi mai multe stoc\u0103ri f\u0103r\u0103 nicio sincronizare \u00eentre ele. Apropiindu-ne de sarcina noastr\u0103, putem:<\/p>\n<p><\/p>\n<ul>\n<li>Separarea fi\u0219ierelor pe tipuri. De exemplu, imaginile\/video pot fi decodificate \u0219i selectate \u00eentr-un format mai eficient.<\/li>\n<li>Separarea conturilor pe \u021b\u0103ri. Din cauza multor legisla\u021bii, asta poate fi necesar, \u00eens\u0103 aceast\u0103 schem\u0103 arhitectural\u0103 ofer\u0103 aceast\u0103 posibilitate \u00een mod automat.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Modele arhitecturale convenabile\" src=\"\/wp-content\/uploads\/2020\/05\/dd310df700bc39c014d0105a3425fece.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dac\u0103 dori\u021bi s\u0103 transfera\u021bi date de la un stoc la altul, atunci aici nu se poate folosi solu\u021bia standard. Din p\u0103cate, \u00een acest caz, este necesar s\u0103 opri\u021bi coada, s\u0103 face\u021bi migrarea \u0219i apoi s\u0103 o reporni\u021bi. \u00cen general, datele nu pot fi transferate \u201e\u00een zbor\u201d, totu\u0219i, dac\u0103 coada evenimentelor este complet stocat\u0103, \u0219i ave\u021bi copii ale st\u0103rilor anterioare ale stocului, putem repara evenimentele astfel:<\/p>\n<p><\/p>\n<ul>\n<li>\u00cen Event Source, fiecare eveniment are un identificator (ideal - unul care nu scade). Astfel, \u00een stoc, putem ad\u0103uga un c\u00e2mp - id-ul ultimului element procesat.<\/li>\n<li>Duplic\u0103m coada, astfel \u00eenc\u00e2t toate evenimentele s\u0103 poat\u0103 fi procesate pentru mai multe stocuri independente (primul este cel \u00een care datele sunt deja stocate, iar al doilea este nou, \u00eens\u0103 momentan gol). A doua coad\u0103, evident, nu este \u00eenc\u0103 procesat\u0103.<\/li>\n<li>Lans\u0103m a doua coad\u0103 (adic\u0103 \u00eencepem reintroducerea evenimentelor).<\/li>\n<li>C\u00e2nd noua coad\u0103 va fi relativ goal\u0103 (adic\u0103 diferen\u021ba medie \u00een timp \u00eentre ad\u0103ugarea unui element \u0219i extragerea acestuia va fi acceptabil\u0103), putem \u00eencepe s\u0103 comut\u0103m cititorii pe noul stoc.<\/li>\n<\/ul>\n<p><\/p>\n<p>A\u0219a cum se vede, sistemul nostru nu a avut \u0219i nu are o coeren\u021b\u0103 strict\u0103. Exist\u0103 doar coeren\u021b\u0103 eventual\u0103, ceea ce \u00eenseamn\u0103 c\u0103 evenimentele sunt procesate \u00een aceea\u0219i ordine (\u00eens\u0103, posibil, cu \u00eent\u00e2rziere diferit\u0103). \u0218i, folosind asta, putem transfera datele relativ u\u0219or f\u0103r\u0103 a opri sistemul dintr-un cap\u0103t al lumii \u00een altul.<\/p>\n<p><\/p>\n<p>Astfel, continu\u00e2nd exemplul nostru despre stocarea online a fi\u0219ierelor, aceast\u0103 arhitectur\u0103 ne ofer\u0103 deja o serie de bonusuri:<\/p>\n<p><\/p>\n<ul>\n<li>Putem muta obiecte mai aproape de utilizatori, \u00eentr-un mod dinamic. Astfel, putem \u00eembun\u0103t\u0103\u021bi calitatea serviciului. <\/li>\n<li>Putem stoca o parte din date \u00een interiorul companiilor. De exemplu, utilizatorii Enterprise solicit\u0103 adesea s\u0103 \u00ee\u0219i stocheze datele \u00een centre de date controlate (pentru a evita scurgerile de date). Prin sharding, putem sus\u021bine u\u0219or acest lucru. \u0218i sarcina devine \u0219i mai simpl\u0103 dac\u0103 clientul are un cloud compatibil (de exemplu, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.microsoft.com\/en-gb\/azure-stack\/asdk\/asdk-what-is?view=azs-1910\">Azure self hosted<\/a><\/noindex>).<\/li>\n<li>Cel mai important este c\u0103 nu suntem obliga\u021bi s\u0103 facem asta. De fapt, la \u00eenceput ne-ar ajunge un singur depozit pentru toate conturile (pentru a \u00eencepe rapid lucrul). O caracteristic\u0103 cheie a acestui sistem este c\u0103, de\u0219i este extins, la etapa ini\u021bial\u0103 este suficient de simplu. Pur \u0219i simplu nu trebuie s\u0103 scriem din prima cod care lucreaz\u0103 cu milioane de cozi independente etc. Dac\u0103 va fi necesar, acest lucru poate fi realizat \u00een viitor.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"static-content-hosting\">G\u0103zduire de con\u021binut static<\/h1>\n<p><\/p>\n<p>Acest punct poate p\u0103rea evident, dar este totu\u0219i necesar pentru o aplica\u021bie standard cu o \u00eenc\u0103rcare mai mare. Esen\u021ba sa este simpl\u0103: tot con\u021binutul static este livrat nu de pe acelasi server cu aplica\u021bia, ci de pe servere dedicate \u00een acest scop. Ca urmare, aceste opera\u021bii se desf\u0103\u0219oar\u0103 mai repede (de exemplu, nginx livreaz\u0103 fi\u0219ierele mai rapid \u0219i mai eficient dec\u00e2t un server Java). \u00cen plus, arhitectura CDN (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Content_delivery_network\">Re\u021bea de livrare a con\u021binutului<\/a><\/noindex>) permite plasarea fi\u0219ierelor noastre mai aproape de utilizatorii finali, ceea ce \u00eembun\u0103t\u0103\u021be\u0219te experien\u021ba de utilizare a serviciului.<\/p>\n<p><\/p>\n<p>Cel mai simplu \u0219i standard exemplu de con\u021binut static este un set de scripturi \u0219i imagini pentru un site. Este simplu \u2014 acestea sunt cunoscute dinainte, apoi arhiva este \u00eenc\u0103rcat\u0103 pe serverele CDN, de unde sunt livrate utilizatorilor finali.<\/p>\n<p><\/p>\n<p>Cu toate acestea, \u00een practic\u0103, pentru con\u021binutul static se poate aplica o abordare similar\u0103 arhitecturii lambda. S\u0103 ne \u00eentoarcem la sarcina noastr\u0103 (depozitul online de fi\u0219iere), \u00een care trebuie s\u0103 livr\u0103m fi\u0219iere utilizatorilor. Cea mai simpl\u0103 solu\u021bie ar fi s\u0103 facem un serviciu care, pentru fiecare cerere a utilizatorului, face toate verific\u0103rile necesare (autorizare etc.), \u0219i apoi descarc\u0103 fi\u0219ierul direct de la depozitul nostru. Principalul dezavantaj al acestei abord\u0103ri este c\u0103 con\u021binutul static (iar un fi\u0219ier cu o revizie specific\u0103 este, \u00een esen\u021b\u0103, con\u021binut static) este livrat de acela\u0219i server care con\u021bine logica de afaceri. \u00cen loc de aceasta, putem crea urm\u0103toarea schem\u0103:<\/p>\n<p><\/p>\n<ul>\n<li>Serverul ofer\u0103 un URL pentru desc\u0103rcare. Acesta poate fi \u00een forma file_id + key, unde key este o semn\u0103tur\u0103 digital\u0103 minim\u0103 care ofer\u0103 dreptul de acces la resurs\u0103 timp de aproape o zi.<\/li>\n<li>Livrarea fi\u0219ierelor este gestionat\u0103 de un simplu nginx cu urm\u0103toarele op\u021biuni:\n<ul>\n<li>Cache-ul de con\u021binut. Deoarece acest serviciu poate fi pe un server separat, ne-am l\u0103sat o rezerv\u0103 pentru viitor, av\u00e2nd posibilitatea de a stoca toate fi\u0219ierele desc\u0103rcate recent pe disc.<\/li>\n<li>Verificarea cheii \u00een momentul cre\u0103rii conexiunii<\/li>\n<\/ul>\n<\/li>\n<li>Op\u021bional: procesarea de con\u021binut \u00een flux. De exemplu, dac\u0103 comprim\u0103m toate fi\u0219ierele \u00een serviciu, putem efectua dezirhivarea direct \u00een acest modul. Ca urmare: opera\u021biile IO sunt realizate acolo unde li se potrivesc cel mai bine. Un arhivator pe Java va consuma mult\u0103 memorie suplimentar\u0103, dar rescrierea serviciului cu logica de afaceri \u00een Rust\/C++ ar putea fi, de asemenea, ineficient\u0103. \u00cen cazul nostru, se folosesc procese diferite (sau chiar servicii), astfel \u00eenc\u00e2t logica de afaceri \u0219i opera\u021biile IO pot fi separate destul de eficient.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Modele arhitecturale convenabile\" src=\"\/wp-content\/uploads\/2020\/05\/4dead07d5824938e09b986192ccc8f5e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aceast\u0103 schem\u0103 nu seam\u0103n\u0103 foarte mult cu livrarea con\u021binutului static (deoarece nu descarg\u0103m \u00eentregul pachet de statice undeva), dar \u00een realitate, aceast\u0103 abordare se ocup\u0103 de livrarea datelor imuabile. Mai mult, aceast\u0103 schem\u0103 poate fi generalizat\u0103 pentru alte cazuri, c\u00e2nd con\u021binutul nu este doar static, ci poate fi reprezentat ca un set de blocuri imuabile \u0219i nedep\u0103\u0219ite (de\u0219i pot fi ad\u0103ugate).<\/p>\n<p><\/p>\n<p>Un alt exemplu (pentru a \u00eent\u0103ri): dac\u0103 a\u021bi lucrat cu Jenkins\/TeamCity, \u0219ti\u021bi c\u0103 ambele solu\u021bii sunt scrise \u00een Java. Ambele reprezint\u0103 un proces Java, care se ocup\u0103 at\u00e2t de orchestrarea build-urilor, c\u00e2t \u0219i de managementul con\u021binutului. \u00cen special, ambele au sarcini de genul &quot;transfera\u021bi fi\u0219ierul\/folderul de pe server&quot;. Ca exemplu: livrarea artefactelor, transferul codului surs\u0103 (atunci c\u00e2nd agentul nu descarc\u0103 codul direct din repository, ci serverul se ocup\u0103 de asta), accesul la loguri. Toate aceste sarcini difer\u0103 prin sarcina pe IO. Asta \u00eenseamn\u0103 c\u0103 serverul, care se ocup\u0103 de logica de afaceri complex\u0103, trebuie de asemenea s\u0103 fie capabil s\u0103 gestioneze eficient fluxuri mari de date. \u0218i ceea ce este cel mai interesant, o astfel de opera\u021biune poate fi delegat\u0103 aceluia\u0219i nginx \u00een exact aceea\u0219i schem\u0103 (cu condi\u021bia ca \u00een cerere s\u0103 se adauge cheia de date).<\/p>\n<p><\/p>\n<p>Totu\u0219i, dac\u0103 ne \u00eentoarcem la sistemul nostru, rezult\u0103 o schem\u0103 similar\u0103:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Modele arhitecturale convenabile\" src=\"\/wp-content\/uploads\/2020\/05\/97cfbf5daaa6678a9eecc3169692f0fc.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dup\u0103 cum se poate observa, sistemul s-a complicat radical. Acum nu este doar un mini-proces care stocheaz\u0103 fi\u0219iere local. Acum este necesar\u0103 o sus\u021binere mai complex\u0103, controlul versiunilor API etc. De aceea, dup\u0103 ce toate diagramele sunt desenate, este cel mai bine s\u0103 evalu\u0103m \u00een detaliu dac\u0103 scalabilitatea implic\u0103 astfel de costuri. Totu\u0219i, dac\u0103 dori\u021bi s\u0103 ave\u021bi posibilitatea de a extinde sistemul (inclusiv pentru a lucra cu un num\u0103r \u0219i mai mare de utilizatori), va trebui s\u0103 lua\u021bi astfel de decizii. Din fericire, ca rezultat, arhitectura sistemului este preg\u0103tit\u0103 pentru cre\u0219terea \u00eenc\u0103rc\u0103turii (practic fiecare component\u0103 poate fi clonat\u0103 pentru scalarea orizontal\u0103). Sistemul poate fi actualizat f\u0103r\u0103 a fi oprit (doar anumite opera\u021biuni se vor \u00eencetini u\u0219or).<\/p>\n<p><\/p>\n<p>A\u0219a cum am men\u021bionat la \u00eenceput, acum o serie de servicii online au \u00eenceput s\u0103 suporte o \u00eenc\u0103rc\u0103tur\u0103 crescut\u0103. \u0218i unele dintre ele pur \u0219i simplu au \u00eenceput s\u0103 nu func\u021bioneze corect. Practic, sistemele au cedat exact \u00een momentul \u00een care afacerea ar fi trebuit s\u0103 genereze venituri. Asta \u00eenseamn\u0103 c\u0103, \u00een loc de livr\u0103ri am\u00e2nate, \u00een loc de a oferi clien\u021bilor \u201eplanifica\u021bi livr\u0103rile pentru lunile urm\u0103toare\u201d, sistemul a spus pur \u0219i simplu \u201emerge\u021bi la concuren\u021bi\u201d. Aceasta este, de fapt, pre\u021bul unei performan\u021be sc\u0103zute: pierderile vor ap\u0103rea exact atunci c\u00e2nd profitul ar fi fost cel mai mare.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Concluzie<\/h1>\n<p><\/p>\n<p>Toate aceste abord\u0103ri au fost cunoscute \u0219i anterior. De exemplu, VK utilizeaz\u0103 de mult timp ideea de Hosting pentru Con\u021binut Static pentru a livra imagini. O mul\u021bime de jocuri online folosesc schema de Sharding pentru a \u00eemp\u0103r\u021bi juc\u0103torii pe regiuni sau pentru a separa loca\u021biile de joc (dac\u0103 lumea este unitar\u0103). Abordarea Event Sourcing este utilizat\u0103 activ \u00een e-mail. Majoritatea aplica\u021biilor traderilor, unde datele sosesc continuu, sunt de fapt construite pe abordarea CQRS pentru a avea capacitatea de a filtra datele primite. Iar scalarea orizontal\u0103 este utilizat\u0103 de mult timp \u00een multe servicii.<\/p>\n<p><\/p>\n<p>\u00cens\u0103, ceea ce este cel mai important, toate aceste modele au devenit foarte u\u0219or de aplicat \u00een aplica\u021biile moderne (dac\u0103 sunt adecvate, desigur). Cloud-urile ofer\u0103 Sharding \u0219i scalare orizontal\u0103 imediat, ceea ce este mult mai simplu dec\u00e2t s\u0103 comanzi servere dedicate \u00een centre de date diferite de unul singur. CQRS a devenit mult mai simplu, cel pu\u021bin datorit\u0103 dezvolt\u0103rii bibliotecilor, cum ar fi RX. Cu 10 ani \u00een urm\u0103, un site web rar ar fi putut s\u0103 sus\u021bin\u0103 a\u0219a ceva. Event Sourcing se configureaz\u0103 de asemenea incredibil de u\u0219or datorit\u0103 containerelor deja preg\u0103tite cu Apache Kafka. Acum 10 ani, acest lucru ar fi fost o inova\u021bie, iar acum este o normalitate. La fel \u0219i cu Static Content Hosting: datorit\u0103 tehnologiilor mai convenabile (inclusiv pentru c\u0103 exist\u0103 documenta\u021bie detaliat\u0103 \u0219i o baz\u0103 mare de r\u0103spunsuri), o astfel de abordare a devenit \u0219i mai simpl\u0103.<\/p>\n<p><\/p>\n<p>Ca urmare, implementarea unei serii de modele arhitecturale destul de complexe a devenit acum mult mai u\u0219oar\u0103, ceea ce \u00eenseamn\u0103 c\u0103 ar trebui s\u0103 fie luat\u0103 \u00een considerare din timp. Dac\u0103 \u00eentr-o aplica\u021bie de acum zece ani s-a renun\u021bat la una dintre solu\u021biile de mai sus din cauza costurilor ridicate de implementare \u0219i \u00eentre\u021binere, acum, \u00een noua aplica\u021bie, sau dup\u0103 o refactorizare, se poate crea un serviciu care arhitectural va fi at\u00e2t scalabil (din punct de vedere al performan\u021bei), c\u00e2t \u0219i preg\u0103tit pentru cerin\u021be noi din partea clien\u021bilor (de exemplu, pentru localizarea datelor personale).<\/p>\n<p><\/p>\n<p>\u0218i cel mai important: nu folosi\u021bi, v\u0103 rog, aceste abord\u0103ri dac\u0103 ave\u021bi o aplica\u021bie simpl\u0103. Da, sunt frumoase \u0219i interesante, \u00eens\u0103 pentru un site cu un v\u00e2rf de 100 de vizitatori, adesea se poate miza pe un monolit clasic (cel pu\u021bin din exterior, \u00een interior totul poate fi spart \u00een module etc.).<\/p>\n<p>Sursa: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/dbtc\/blog\/499758\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0430 \u0438\u0437 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 \u0432 \u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0430 \u0441\u0430\u0439\u0442 \u0441 \u043e\u043d\u043b\u0430\u0439\u043d-\u0437\u0430\u043a\u0430\u0437\u0430\u043c\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u043b\u043e \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0435\u0439. \u0418 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0431\u043e\u043b\u0435\u0435 \u043c\u043e\u0449\u043d\u043e\u0435 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u043e\u0434\u043d\u0430\u043a\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0434\u043e (\u0438\u043b\u0438 \u043e\u043d\u0438 \u0443\u0439\u0434\u0443\u0442 \u043a \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u0430\u043c). \u0412 \u044d\u0442\u043e\u0439 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":80036,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-80035","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0423\u0434\u043e\u0431\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-05-02T11:42:54+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-02T11:42:54+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Modele arhitecturale convenabile | ProHoster","description":"Salut, Habr! \u00cen lumina evenimentelor curente cauzate de coronavirus, o serie de servicii internet au \u00eenceput s\u0103 primeasc\u0103 o \u00eenc\u0103rc\u0103tur\u0103 crescut\u0103.","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0423\u0434\u043e\u0431\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b | ProHoster","og:description":"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0412 \u0441\u0432\u0435\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441\u0430 \u0440\u044f\u0434 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0442\u0430\u043b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443.","og:url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-05-02T11:42:54+00:00","article:modified_time":"2020-05-02T11:42:54+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"80035","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:26:40","updated":"2022-09-28 01:38:29","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/80035","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=80035"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/80035\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media\/80036"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=80035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=80035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=80035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}