{"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\/cs\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","title":{"rendered":"Pohodln\u00e9 architektonick\u00e9 vzory","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ahoj, Habr!<\/p>\n<p><\/p>\n<p>Vzhledem k sou\u010dasn\u00fdm ud\u00e1lostem zp\u016fsoben\u00fdm koronavirem za\u010dalo n\u011bkolik internetov\u00fdch slu\u017eeb za\u017e\u00edvat zv\u00fd\u0161enou z\u00e1t\u011b\u017e. Nap\u0159\u00edklad, <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\">jedna z maloobchodn\u00edch s\u00edt\u00ed ve Velk\u00e9 Brit\u00e1nii jednodu\u0161e pozastavila web s online objedn\u00e1vkami<\/a><\/noindex>, proto\u017ee jim do\u0161ly kapacity. A ne v\u017edy je mo\u017en\u00e9 zrychlit server jednodu\u0161e p\u0159id\u00e1n\u00edm v\u00fdkonn\u011bj\u0161\u00edho hardwaru, nicm\u00e9n\u011b je t\u0159eba zpracov\u00e1vat po\u017eadavky z\u00e1kazn\u00edk\u016f (jinak odejdou ke konkurenci).<\/p>\n<p><\/p>\n<p>V tomto \u010dl\u00e1nku kr\u00e1tce pop\u00ed\u0161u popul\u00e1rn\u00ed praktiky, kter\u00e9 umo\u017en\u00ed vytvo\u0159it rychlou a odolnou slu\u017ebu. Nicm\u00e9n\u011b jsem vybral pouze ty v\u00fdvojov\u00e9 sch\u00e9mata, kter\u00e9 jsou v sou\u010dasnosti <strong>snadno dostupn\u00e9.<\/strong>Pro ka\u017ed\u00fd bod u\u017e m\u00e1te bu\u010f hotov\u00e9 knihovny, nebo mo\u017enost vy\u0159e\u0161it \u00fakol pomoc\u00ed cloudov\u00e9 platformy.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"gorizontalnoe-masshtabirovanie\">Horizont\u00e1ln\u00ed \u0161k\u00e1lov\u00e1n\u00ed<\/h1>\n<p><\/p>\n<p>Nejjednodu\u0161\u0161\u00ed a v\u0161em zn\u00e1m\u00fd bod. Obvykle se nej\u010dast\u011bji setk\u00e1v\u00e1me se dv\u011bma sch\u00e9maty rozd\u011blen\u00ed z\u00e1t\u011b\u017ee \u2014 horizont\u00e1ln\u00edm a vertik\u00e1ln\u00edm \u0161k\u00e1lov\u00e1n\u00edm. <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\">V prvn\u00edm p\u0159\u00edpad\u011b<\/a><\/noindex> dovolujete slu\u017eb\u00e1m pracovat paraleln\u011b, \u010d\u00edm\u017e rozd\u011blujete z\u00e1t\u011b\u017e mezi nimi. <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\">Ve druh\u00e9m<\/a><\/noindex> objedn\u00e1v\u00e1te v\u00fdkonn\u011bj\u0161\u00ed servery nebo optimalizujete k\u00f3d.<\/p>\n<p><\/p>\n<p>Jako p\u0159\u00edklad vezmu abstraktn\u00ed cloudov\u00e9 \u00falo\u017ei\u0161t\u011b soubor\u016f, tedy ur\u010dit\u00fd analog OwnCloud, OneDrive a tak d\u00e1le.<\/p>\n<p><\/p>\n<p>Standardn\u00ed obr\u00e1zek podobn\u00e9ho sch\u00e9matu je n\u00ed\u017ee, nicm\u00e9n\u011b pouze demonstruje slo\u017eitost syst\u00e9mu. Proto\u017ee mus\u00edme n\u011bjak synchronizovat slu\u017eby. Co se stane, pokud u\u017eivatel ulo\u017e\u00ed soubor z tabletu a pak ho chce zobrazit na mobilu?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pohodln\u00e9 architektonick\u00e9 vzory\" src=\"\/wp-content\/uploads\/2020\/05\/7512c6d8783f5e0a38cc0861b01e54c8.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nRozd\u00edl mezi p\u0159\u00edstupy: u vertik\u00e1ln\u00edho \u0161k\u00e1lov\u00e1n\u00ed jsme p\u0159ipraveni zvy\u0161ovat v\u00fdkon uzl\u016f, zat\u00edmco u horizont\u00e1ln\u00edho \u2014 p\u0159id\u00e1vat nov\u00e9 uzly pro rozd\u011blen\u00ed z\u00e1t\u011b\u017ee.<\/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\">Segmentace odpov\u011bdnosti dotazu a p\u0159\u00edkazu<\/a><\/noindex> je docela d\u016fle\u017eit\u00fd vzor, proto\u017ee umo\u017e\u0148uje r\u016fzn\u00fdm klient\u016fm nejen p\u0159ipojit se k r\u016fzn\u00fdm slu\u017eb\u00e1m, ale tak\u00e9 dost\u00e1vat stejn\u00e9 proudy ud\u00e1lost\u00ed. Jeho v\u00fdhody nejsou tak z\u0159ejm\u00e9 pro jednoduchou aplikaci, nicm\u00e9n\u011b je nesm\u00edrn\u011b d\u016fle\u017eit\u00fd (a jednoduch\u00fd) pro zat\u00ed\u017een\u00e9 slu\u017eby. Jeho podstata spo\u010d\u00edv\u00e1 v tom, \u017ee p\u0159\u00edchoz\u00ed a odchoz\u00ed toky dat se nesm\u00ed p\u0159ekr\u00fdvat. To znamen\u00e1, \u017ee nem\u016f\u017eete poslat po\u017eadavek a o\u010dek\u00e1vat odpov\u011b\u010f, m\u00edsto toho pos\u00edl\u00e1te po\u017eadavek do slu\u017eby A, ale odpov\u011b\u010f dost\u00e1v\u00e1te ve slu\u017eb\u011b B.<\/p>\n<p><\/p>\n<p>Prvn\u00ed v\u00fdhodou tohoto p\u0159\u00edstupu je mo\u017enost p\u0159eru\u0161en\u00ed spojen\u00ed (v \u0161irok\u00e9m smyslu tohoto slova) b\u011bhem prov\u00e1d\u011bn\u00ed dlouh\u00e9ho dotazu. Jako p\u0159\u00edklad zva\u017eme v\u00edce m\u00e9n\u011b standardn\u00ed sekvenci:<\/p>\n<p><\/p>\n<ol>\n<li>Klient odeslal dotaz na server.<\/li>\n<li>Server zah\u00e1jil dlouh\u00e9 zpracov\u00e1n\u00ed.<\/li>\n<li>Server odpov\u011bd\u011bl klientovi v\u00fdsledkem.<\/li>\n<\/ol>\n<p><\/p>\n<p>P\u0159edstavme si, \u017ee v bod\u011b 2 do\u0161lo k p\u0159eru\u0161en\u00ed spojen\u00ed (nebo se s\u00ed\u0165 p\u0159econnectovala, nebo u\u017eivatel p\u0159e\u0161el na jinou str\u00e1nku a p\u0159eru\u0161il spojen\u00ed). V takov\u00e9m p\u0159\u00edpad\u011b by bylo serveru obt\u00ed\u017en\u00e9 poslat odpov\u011b\u010f u\u017eivateli s informac\u00ed, co bylo pr\u00e1v\u011b zpracov\u00e1no. Aplikac\u00ed CQRS bude sekvence trochu jin\u00e1:<\/p>\n<p><\/p>\n<ol>\n<li>Klient se p\u0159ihl\u00e1sil k odb\u011bru aktualizac\u00ed.<\/li>\n<li>Klient odeslal dotaz na server.<\/li>\n<li>Server odpov\u011bd\u011bl 'po\u017eadavek p\u0159ijat'.<\/li>\n<li>Server odpov\u011bd\u011bl v\u00fdsledkem prost\u0159ednictv\u00edm kan\u00e1lu z bodu '1'.<\/li>\n<\/ol>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pohodln\u00e9 architektonick\u00e9 vzory\" src=\"\/wp-content\/uploads\/2020\/05\/8a00ea93eecc7cc0754122857c5f90d0.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jak vidno, sch\u00e9ma je o n\u011bco slo\u017eit\u011bj\u0161\u00ed. Nav\u00edc intuitivn\u00ed p\u0159\u00edstup request-response zde chyb\u00ed. Nicm\u00e9n\u011b jak vidno, p\u0159eru\u0161en\u00ed spojen\u00ed b\u011bhem zpracov\u00e1n\u00ed dotazu nepovede k chyb\u011b. Co v\u00edce, pokud je u\u017eivatel skute\u010dn\u011b p\u0159ipojen k slu\u017eb\u011b z v\u00edce za\u0159\u00edzen\u00ed (nap\u0159\u00edklad z mobiln\u00edho telefonu a tabletu), lze zajistit, aby odpov\u011b\u010f p\u0159i\u0161la na ob\u011b za\u0159\u00edzen\u00ed.<\/p>\n<p><\/p>\n<p>Co je zaj\u00edmav\u00e9, k\u00f3d zpracov\u00e1n\u00ed p\u0159\u00edchoz\u00edch zpr\u00e1v se st\u00e1v\u00e1 stejn\u00fdm (ne na 100 %) jak pro ud\u00e1losti, na kter\u00e9 m\u011bl vliv s\u00e1m klient, tak pro ostatn\u00ed ud\u00e1losti, v\u010detn\u011b t\u011bch od jin\u00fdch klient\u016f.<\/p>\n<p><\/p>\n<p>V re\u00e1lu v\u0161ak z\u00edsk\u00e1v\u00e1me dal\u0161\u00ed v\u00fdhody d\u00edky tomu, \u017ee jednosm\u011brn\u00fd tok lze zpracov\u00e1vat funkcion\u00e1ln\u00edm stylem (pou\u017e\u00edvaj\u00edc\u00ed RX a analogie). A to u\u017e je v\u00e1\u017en\u00fd plus, proto\u017ee v podstat\u011b lze aplikaci ud\u011blat zcela reaktivn\u00ed, nav\u00edc s implementac\u00ed funkcion\u00e1ln\u00edho p\u0159\u00edstupu. Pro robustn\u00ed aplikace to m\u016f\u017ee v\u00fdrazn\u011b u\u0161et\u0159it zdroje na v\u00fdvoj a \u00fadr\u017ebu.<\/p>\n<p><\/p>\n<p>Pokud tento p\u0159\u00edstup spoj\u00edme s horizont\u00e1ln\u00edm \u0161k\u00e1lov\u00e1n\u00edm, z\u00edsk\u00e1v\u00e1me mo\u017enost odes\u00edlat dotazy na jeden server, ale p\u0159ij\u00edmat odpov\u011bdi od jin\u00e9ho. T\u00edmto zp\u016fsobem si klient m\u016f\u017ee s\u00e1m vybrat pohodlnou slu\u017ebu a syst\u00e9m uvnit\u0159 si stejn\u011b dok\u00e1\u017ee spr\u00e1vn\u011b zpracovat ud\u00e1losti.<\/p>\n<p><\/p>\n<h1 id=\"event-sourcing\">Event Sourcing<\/h1>\n<p><\/p>\n<p>Jak v\u00edte, jednou z hlavn\u00edch vlastnost\u00ed distribuovan\u00fdch syst\u00e9m\u016f je absence spole\u010dn\u00e9ho \u010dasu a spole\u010dn\u00e9 kritick\u00e9 sekce. Pro jeden proces m\u016f\u017eete ud\u011blat synchronizaci (na stejn\u00fdch mutexech), b\u011bhem n\u00ed\u017e m\u00e1te jistotu, \u017ee nikdo jin\u00fd tento k\u00f3d nevykon\u00e1v\u00e1. Av\u0161ak pro distribuovan\u00fd syst\u00e9m je to nebezpe\u010dn\u00e9, proto\u017ee by to p\u0159ineslo n\u00e1klady na synchronizaci a z\u00e1rove\u0148 by se zabil cel\u00fd p\u016fvab \u0161k\u00e1lovatelnosti \u2014 v\u0161echny komponenty by p\u0159esto \u010dekaly na jednu.<\/p>\n<p><\/p>\n<p>Odtud z\u00edsk\u00e1v\u00e1me d\u016fle\u017eit\u00fd fakt \u2014 rychl\u00fd distribuovan\u00fd syst\u00e9m nelze synchronizovat, proto\u017ee bychom t\u00edm sn\u00ed\u017eili v\u00fdkon. Na druhou stranu, \u010dasto pot\u0159ebujeme ur\u010ditou konzistenci komponent. A k tomu lze pou\u017e\u00edt p\u0159\u00edstup s <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>, kde je zaru\u010deno, \u017ee v p\u0159\u00edpad\u011b absence zm\u011bn dat po ur\u010dit\u00e9m \u010dasov\u00e9m obdob\u00ed od posledn\u00ed aktualizace (\u201ev kone\u010dn\u00e9m d\u016fsledku\u201c) budou v\u0161echny po\u017eadavky vracet posledn\u00ed aktualizovanou hodnotu.<\/p>\n<p><\/p>\n<p>Je d\u016fle\u017eit\u00e9 ch\u00e1pat, \u017ee pro klasick\u00e9 datab\u00e1ze se \u010dasto pou\u017e\u00edv\u00e1 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Consistency_model#Strict_consistency\">p\u0159\u00edsn\u00e1 konzistence<\/a><\/noindex>, kde ka\u017ed\u00fd uzel m\u00e1 stejn\u00e9 informace (toho se \u010dasto dosahuje v situaci, kdy je transakce pova\u017eov\u00e1na za dokon\u010denou a\u017e po odpov\u011bdi druh\u00e9ho serveru). Zde existuj\u00ed ur\u010dit\u00e9 \u00falevy z d\u016fvodu \u00farovn\u00ed izolace, nicm\u00e9n\u011b celkov\u00e1 podstata z\u016fst\u00e1v\u00e1 stejn\u00e1 \u2014 m\u016f\u017eete \u017e\u00edt v pln\u011b konzistentn\u00edm sv\u011bt\u011b.<\/p>\n<p><\/p>\n<p>Ale vra\u0165me se k p\u016fvodn\u00edmu \u00fakolu. Pokud m\u016f\u017ee b\u00fdt \u010d\u00e1st syst\u00e9mu postavena s <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>, lze postavit n\u00e1sleduj\u00edc\u00ed sch\u00e9ma.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pohodln\u00e9 architektonick\u00e9 vzory\" src=\"\/wp-content\/uploads\/2020\/05\/33c80be6bc33bd897ca9b9e5525f9ae8.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hlavn\u00ed rysy tohoto p\u0159\u00edstupu:<\/p>\n<p><\/p>\n<ul>\n<li>Ka\u017ed\u00fd p\u0159\u00edchoz\u00ed po\u017eadavek je um\u00edst\u011bn do jedn\u00e9 fronty.<\/li>\n<li>B\u011bhem zpracov\u00e1n\u00ed po\u017eadavku m\u016f\u017ee slu\u017eba tak\u00e9 um\u00edstit \u00fakoly do jin\u00fdch front.<\/li>\n<li>Ka\u017ed\u00e1 p\u0159\u00edchoz\u00ed ud\u00e1lost m\u00e1 identifik\u00e1tor (kter\u00fd je pot\u0159ebn\u00fd pro deduplikaci).<\/li>\n<li>Fronta funguje ideologicky na principu \"pouze p\u0159idat\". Nelze z n\u00ed odstra\u0148ovat prvky ani je p\u0159esouvat.<\/li>\n<li>Fronta pracuje podle sch\u00e9matu FIFO (omlouv\u00e1m se za tautologii). Pokud je nutn\u00e9 prov\u00e9st paraleln\u00ed zpracov\u00e1n\u00ed, je t\u0159eba v jednom z krok\u016f p\u0159esunout objekty do r\u016fzn\u00fdch front.<\/li>\n<\/ul>\n<p><\/p>\n<p>P\u0159ipom\u00edn\u00e1m, \u017ee zva\u017eujeme p\u0159\u00edpad online \u00falo\u017ei\u0161t\u011b soubor\u016f. V tomto p\u0159\u00edpad\u011b bude syst\u00e9m vypadat p\u0159ibli\u017en\u011b takto:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pohodln\u00e9 architektonick\u00e9 vzory\" src=\"\/wp-content\/uploads\/2020\/05\/b95efb29545dcde1db9432d12d00a1b1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Je d\u016fle\u017eit\u00e9 si uv\u011bdomit, \u017ee slu\u017eby v diagramu nemus\u00ed nutn\u011b znamenat samostatn\u00fd server. I proces m\u016f\u017ee b\u00fdt stejn\u00fd. D\u016fle\u017eit\u00e9 je n\u011bco jin\u00e9ho: ideologicky jsou tyto v\u011bci rozd\u011bleny tak, aby bylo mo\u017en\u00e9 snadno uplatnit horizont\u00e1ln\u00ed \u0161k\u00e1lov\u00e1n\u00ed.<\/p>\n<p><\/p>\n<p>A pro dva u\u017eivatele bude sch\u00e9ma vypadat takto (slu\u017eby ur\u010den\u00e9 r\u016fzn\u00fdm u\u017eivatel\u016fm jsou ozna\u010deny r\u016fzn\u00fdmi barvami):<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pohodln\u00e9 architektonick\u00e9 vzory\" src=\"\/wp-content\/uploads\/2020\/05\/4c4aadc8b9dd505c3ad743e69fee4fae.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>V\u00fdhody takov\u00e9 kombinace:<\/p>\n<p><\/p>\n<ul>\n<li>Slu\u017eby zpracov\u00e1n\u00ed informac\u00ed jsou rozd\u011bleny. Fronty jsou tak\u00e9 rozd\u011bleny. Pokud budeme pot\u0159ebovat zv\u00fd\u0161it propustnost syst\u00e9mu, sta\u010d\u00ed spustit v\u00edce slu\u017eeb na v\u011bt\u0161\u00edm po\u010dtu server\u016f.<\/li>\n<li>Kdy\u017e dostaneme informace od u\u017eivatele, nemus\u00edme se nutn\u011b do\u010dkat \u00fapln\u00e9ho ulo\u017een\u00eda dat. Naopak, sta\u010d\u00ed odpov\u011bd\u011bt \"ok\" a potom postupn\u011b za\u010d\u00edt pracovat. Fronta z\u00e1rove\u0148 vyhlazuje \u0161pi\u010dky, proto\u017ee p\u0159id\u00e1n\u00ed nov\u00e9ho objektu prob\u00edh\u00e1 rychle a u\u017eivatel nemus\u00ed \u010dekat na \u00fapln\u00e9 projit\u00ed cel\u00fdm cyklem.<\/li>\n<li>Pro p\u0159\u00edklad jsem p\u0159idal slu\u017ebu deduplikace, kter\u00e1 se sna\u017e\u00ed spojit stejn\u00e9 soubory. Pokud pracuje dlouho v 1 % p\u0159\u00edpad\u016f, klient toho t\u00e9m\u011b\u0159 nezaznamen\u00e1 (viz v\u00fd\u0161e), co\u017e je velk\u00e9 plus, proto\u017ee od n\u00e1s u\u017e nen\u00ed vy\u017eadov\u00e1na stoprocentn\u00ed rychlost a spolehlivost.<\/li>\n<\/ul>\n<p><\/p>\n<p>Nicm\u00e9n\u011b okam\u017eit\u011b jsou viditeln\u00e9 i nev\u00fdhody:<\/p>\n<p><\/p>\n<ul>\n<li>Na\u0161e syst\u00e9m ztratil p\u0159\u00edsnou konzistenci. To znamen\u00e1, \u017ee pokud se nap\u0159\u00edklad p\u0159ihl\u00e1s\u00edte k r\u016fzn\u00fdm slu\u017eb\u00e1m, teoreticky m\u016f\u017eete z\u00edskat r\u016fzn\u00e9 stavy (proto\u017ee jedna ze slu\u017eeb m\u016f\u017ee m\u00edt probl\u00e9m p\u0159ijmout ozn\u00e1men\u00ed z intern\u00ed fronty). Jako dal\u0161\u00ed d\u016fsledek, syst\u00e9m nyn\u00ed nem\u00e1 spole\u010dn\u00fd \u010das. To znamen\u00e1, \u017ee nelze nap\u0159\u00edklad t\u0159\u00eddit v\u0161echny ud\u00e1losti jednodu\u0161e podle \u010dasu p\u0159\u00edchodu, proto\u017ee hodiny mezi servery nemus\u00ed b\u00fdt synchronizovan\u00e9 (nav\u00edc stejn\u00e9 \u010dasov\u00e9 \u00fadaje na dvou serverech jsou utopie).<\/li>\n<li>\u017d\u00e1dn\u00e9 ud\u00e1losti nelze nyn\u00ed jednodu\u0161e vr\u00e1tit zp\u011bt (jak by to bylo mo\u017en\u00e9 ud\u011blat s datab\u00e1z\u00ed). M\u00edsto toho je nutn\u00e9 p\u0159idat novou ud\u00e1lost \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/49451237\/compensating-events-on-cqrs-es-architecture\">compensation event<\/a><\/noindex>, kter\u00e1 zm\u011bn\u00ed posledn\u00ed stav na pot\u0159ebn\u00fd. Jako p\u0159\u00edklad z podobn\u00e9 oblasti: bez p\u0159eps\u00e1n\u00ed historie (co\u017e je \u0161patn\u011b v ur\u010dit\u00fdch p\u0159\u00edpadech) nelze v gitu vr\u00e1tit commit, ale lze prov\u00e9st speci\u00e1ln\u00ed <noindex><a rel=\"nofollow\" href=\"https:\/\/git-scm.com\/docs\/git-revert\">rollback commit<\/a><\/noindex>, kter\u00fd v podstat\u011b jen vr\u00e1t\u00ed star\u00fd stav. V historii v\u0161ak z\u016fstane jak chybn\u00fd commit, tak rollback.<\/li>\n<li>Datov\u00e1 sch\u00e9ma se m\u016f\u017ee m\u011bnit z verze na verzi, av\u0161ak star\u00e9 ud\u00e1losti ji\u017e nen\u00ed mo\u017en\u00e9 aktualizovat na nov\u00fd standard (proto\u017ee ud\u00e1losti se obecn\u011b nemohou m\u011bnit).<\/li>\n<\/ul>\n<p><\/p>\n<p>Jak je vid\u011bt, Event Sourcing se v\u00fdborn\u011b kombinuje s CQRS. Nav\u00edc, realizovat syst\u00e9m s efektivn\u00edmi a pohodln\u00fdmi frontami, ale bez odd\u011blen\u00ed tok\u016f dat, je samo o sob\u011b slo\u017eit\u00e9, nebo\u0165 bude nutn\u00e9 p\u0159id\u00e1vat synchroniza\u010dn\u00ed body, kter\u00e9 vyrovnaj\u00ed ve\u0161ker\u00fd pozitivn\u00ed efekt front. P\u0159i pou\u017eit\u00ed obou p\u0159\u00edstup\u016f najednou je t\u0159eba m\u00edrn\u011b upravit k\u00f3d pr\u00e1ce programu. V na\u0161em p\u0159\u00edpad\u011b, p\u0159i odes\u00edl\u00e1n\u00ed souboru na server, se v odpov\u011bdi objevuje pouze \u201eok\u201c, co\u017e znamen\u00e1, \u017ee \u201eoperace p\u0159id\u00e1n\u00ed souboru byla ulo\u017eena\u201c. Form\u00e1ln\u011b to neznamen\u00e1, \u017ee data jsou ji\u017e dostupn\u00e1 na jin\u00fdch za\u0159\u00edzen\u00edch (nap\u0159\u00edklad slu\u017eba deduplikace m\u016f\u017ee p\u0159estav\u011bt index). Nicm\u00e9n\u011b po n\u011bjak\u00e9m \u010dase dostane klient ozn\u00e1men\u00ed ve stylu \u201esoubor X byl ulo\u017een\u201c.<\/p>\n<p><\/p>\n<p>A jako v\u00fdsledek:<\/p>\n<p><\/p>\n<ul>\n<li>Po\u010det stav\u016f odes\u00edl\u00e1n\u00ed soubor\u016f se zvy\u0161uje: m\u00edsto klasick\u00e9ho \u201esoubor byl odesl\u00e1n\u201c m\u00e1me nyn\u00ed dva: \u201esoubor byl p\u0159id\u00e1n do fronty na serveru\u201c a \u201esoubor byl ulo\u017een ve skladu\u201c. To posledn\u00ed znamen\u00e1, \u017ee ostatn\u00ed za\u0159\u00edzen\u00ed ji\u017e mohou za\u010d\u00edt soubor p\u0159ij\u00edmat (s ohledem na to, \u017ee fronty pracuj\u00ed r\u016fznou rychlost\u00ed).<\/li>\n<li>Vzhledem k tomu, \u017ee informace o odes\u00edl\u00e1n\u00ed nyn\u00ed p\u0159ich\u00e1z\u00ed r\u016fzn\u00fdmi kan\u00e1ly, mus\u00edme vym\u00fd\u0161let \u0159e\u0161en\u00ed, jak z\u00edskat stav zpracov\u00e1n\u00ed souboru. D\u016fsledkem toho je: na rozd\u00edl od klasick\u00e9ho request-response m\u016f\u017ee b\u00fdt klient restartov\u00e1n b\u011bhem zpracov\u00e1n\u00ed souboru, nicm\u00e9n\u011b stav t\u00e9to zpracov\u00e1n\u00ed bude spr\u00e1vn\u00fd. Tento bod funguje vlastn\u011b \u201ez krabice\u201c. V d\u016fsledku toho jsme nyn\u00ed tolerantn\u011bj\u0161\u00ed k chyb\u00e1m.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sharding\">Sharding<\/h1>\n<p><\/p>\n<p>Jak ji\u017e bylo zm\u00edn\u011bno v\u00fd\u0161e, v syst\u00e9mech s event sourcing neexistuje p\u0159\u00edsn\u00e1 konzistence. To znamen\u00e1, \u017ee m\u016f\u017eeme pou\u017e\u00edvat n\u011bkolik \u00falo\u017ei\u0161\u0165 bez jak\u00e9koliv synchronizace mezi nimi. P\u0159ibli\u017eujeme se k na\u0161emu \u00fakolu, m\u016f\u017eeme:<\/p>\n<p><\/p>\n<ul>\n<li>Rozd\u011blovat soubory podle typ\u016f. Nap\u0159\u00edklad obr\u00e1zky\/videa lze dek\u00f3dovat a vybrat efektivn\u011bj\u0161\u00ed form\u00e1t.<\/li>\n<li>Rozd\u011blen\u00ed \u00fa\u010dt\u016f podle zem\u00ed. Z d\u016fvodu mnoha z\u00e1kon\u016f m\u016f\u017ee b\u00fdt n\u011bco takov\u00e9ho nezbytn\u00e9, av\u0161ak tato architektonick\u00e1 sch\u00e9ma tuto mo\u017enost nab\u00edz\u00ed automaticky.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pohodln\u00e9 architektonick\u00e9 vzory\" src=\"\/wp-content\/uploads\/2020\/05\/dd310df700bc39c014d0105a3425fece.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pokud chcete p\u0159en\u00e9st data z jednoho \u00falo\u017ei\u0161t\u011b do druh\u00e9ho, ji\u017e nesta\u010d\u00ed standardn\u00ed prost\u0159edky. Bohu\u017eel je v takov\u00e9m p\u0159\u00edpad\u011b nutn\u00e9 zastavit frontu, prov\u00e9st migraci a pot\u00e9 ji znovu spustit. Obecn\u011b vzato, data nelze p\u0159esunout 'za b\u011bhu', nicm\u00e9n\u011b pokud jsou ud\u00e1losti ve front\u011b ulo\u017eeny kompletn\u011b a m\u00e1te snapshoty p\u0159edchoz\u00edch stav\u016f \u00falo\u017ei\u0161t\u011b, m\u016f\u017eeme ud\u00e1losti opakovat n\u00e1sleduj\u00edc\u00edm zp\u016fsobem:<\/p>\n<p><\/p>\n<ul>\n<li>V Event Source ka\u017ed\u00e1 ud\u00e1lost m\u00e1 sv\u00e9 vlastn\u00ed identifika\u010dn\u00ed \u010d\u00edslo (ide\u00e1ln\u011b se nezmen\u0161uj\u00edc\u00ed). A proto m\u016f\u017eeme do \u00falo\u017ei\u0161t\u011b p\u0159idat pole \u2013 id posledn\u00edho zpracovan\u00e9ho prvku.<\/li>\n<li>Duplikuji frontu, aby v\u0161echny ud\u00e1losti mohly b\u00fdt zpracov\u00e1ny pro n\u011bkolik nez\u00e1visl\u00fdch \u00falo\u017ei\u0161\u0165 (prvn\u00ed je to, ve kter\u00e9m jsou ji\u017e nyn\u00ed ulo\u017eena data, a druh\u00e9 je nov\u00e9, zat\u00edm pr\u00e1zdn\u00e9). Druh\u00e1 fronta je samoz\u0159ejm\u011b zat\u00edm nezpracov\u00e1v\u00e1na.<\/li>\n<li>Spou\u0161t\u00edme druhou frontu (to znamen\u00e1 za\u010d\u00edn\u00e1me opakovat ud\u00e1losti).<\/li>\n<li>Kdy\u017e bude nov\u00e1 fronta relativn\u011b pr\u00e1zdn\u00e1 (tj. pr\u016fm\u011brn\u00fd \u010dasov\u00fd rozd\u00edl mezi p\u0159id\u00e1n\u00edm prvku a jeho vyjmut\u00edm bude p\u0159ijateln\u00fd), m\u016f\u017eeme za\u010d\u00edt p\u0159ep\u00ednat \u010dten\u00e1\u0159e na nov\u00e9 \u00falo\u017ei\u0161t\u011b.<\/li>\n<\/ul>\n<p><\/p>\n<p>Jak je vid\u011bt, v na\u0161em syst\u00e9mu jak nebyla, tak ani nen\u00ed p\u0159\u00edsn\u00e1 konzistence. Existuje pouze eventual consistency, tedy z\u00e1ruka, \u017ee ud\u00e1losti jsou zpracov\u00e1v\u00e1ny ve stejn\u00e9m po\u0159ad\u00ed (ale mo\u017en\u00e1 s r\u016fznou latenc\u00ed). A vyu\u017eit\u00edm toho m\u016f\u017eeme relativn\u011b snadno p\u0159esunout data bez zastaven\u00ed syst\u00e9mu na druhou stranu sv\u011bta.<\/p>\n<p><\/p>\n<p>Tak\u017ee, pokra\u010duj\u00edc\u00ed v na\u0161em p\u0159\u00edkladu online \u00falo\u017ei\u0161t\u011b pro soubory, takov\u00e1 architektura n\u00e1m ji\u017e poskytuje celou \u0159adu v\u00fdhod:<\/p>\n<p><\/p>\n<ul>\n<li>M\u016f\u017eeme p\u0159esouvat objekty bl\u00ed\u017ee k u\u017eivatel\u016fm, a to dynamick\u00fdm zp\u016fsobem. T\u00edmto zp\u016fsobem lze zv\u00fd\u0161it kvalitu slu\u017eby. <\/li>\n<li>M\u016f\u017eeme uchov\u00e1vat \u010d\u00e1st dat uvnit\u0159 firem. Nap\u0159\u00edklad u\u017eivatel\u00e9 Enterprise \u010dasto po\u017eaduj\u00ed uchov\u00e1vat sv\u00e1 data v kontrolovan\u00fdch datov\u00fdch centrech (aby se p\u0159ede\u0161lo \u00fanik\u016fm dat). D\u00edky sharding se n\u00e1m to m\u016f\u017ee snadno podporovat. \u00dakol je je\u0161t\u011b snadn\u011bj\u0161\u00ed, pokud m\u00e1 z\u00e1kazn\u00edk kompatibiln\u00ed cloud (nap\u0159\u00edklad, <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>A to nejd\u016fle\u017eit\u011bj\u0161\u00ed je, \u017ee to nemus\u00edme d\u011blat. Pro za\u010d\u00e1tek n\u00e1m toti\u017e sta\u010d\u00ed jedno \u00falo\u017ei\u0161t\u011b pro v\u0161echny \u00fa\u010dty (abychom mohli rychle za\u010d\u00edt pracovat). Kl\u00ed\u010dovou vlastnost\u00ed tohoto syst\u00e9mu je, \u017ee a\u010dkoliv je roz\u0161i\u0159iteln\u00fd, v po\u010d\u00e1te\u010dn\u00edm st\u00e1diu je dostate\u010dn\u011b jednoduch\u00fd. Nen\u00ed nutn\u00e9 ihned ps\u00e1t k\u00f3d, kter\u00fd pracuje s milionem samostatn\u00fdch nez\u00e1visl\u00fdch front atd. Pokud to bude pot\u0159eba, lze to ud\u011blat v budoucnu.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"static-content-hosting\">Hosting statick\u00e9ho obsahu<\/h1>\n<p><\/p>\n<p>Tento bod se m\u016f\u017ee zd\u00e1t docela z\u0159ejm\u00fd, ale p\u0159esto je nezbytn\u00fd pro v\u00edce \u010di m\u00e9n\u011b standardn\u00ed zat\u00ed\u017eenou aplikaci. Jeho podstata je jednoduch\u00e1: ve\u0161ker\u00fd statick\u00fd obsah je distribuov\u00e1n ne z toho sam\u00e9ho serveru, kde se nach\u00e1z\u00ed aplikace, ale ze speci\u00e1ln\u011b vyhrazen\u00fdch server\u016f. V d\u016fsledku toho jsou tyto operace prov\u00e1d\u011bny rychleji (konven\u010dn\u00ed nginx dod\u00e1v\u00e1 soubory rychleji a s men\u0161\u00edmi n\u00e1klady ne\u017e Java server). Nav\u00edc architektura CDN (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Content_delivery_network\">Content Delivery Network<\/a><\/noindex>) umo\u017e\u0148uje um\u00edstit na\u0161e soubory bl\u00ed\u017ee k koncov\u00fdm u\u017eivatel\u016fm, co\u017e pozitivn\u011b ovliv\u0148uje pohodl\u00ed p\u0159i pou\u017e\u00edv\u00e1n\u00ed slu\u017eby.<\/p>\n<p><\/p>\n<p>Nejjednodu\u0161\u0161\u00ed a standardn\u00ed p\u0159\u00edklad statick\u00e9ho obsahu jsou skripty a obr\u00e1zky pro web. S nimi je v\u0161e jasn\u00e9 - jsou zn\u00e1my p\u0159edem, pot\u00e9 se archiv nahr\u00e1v\u00e1 na servery CDN, odkud jsou distribuov\u00e1ny koncov\u00fdm u\u017eivatel\u016fm.<\/p>\n<p><\/p>\n<p>Ve skute\u010dnosti v\u0161ak pro statick\u00fd obsah lze aplikovat p\u0159\u00edstup podobn\u00fd lambda architektu\u0159e. Vra\u0165me se k na\u0161emu \u00fakolu (online \u00falo\u017ei\u0161t\u011b soubor\u016f), v n\u011bm\u017e je t\u0159eba distribuovat soubory u\u017eivatel\u016fm. Nejjednodu\u0161\u0161\u00ed \u0159e\u0161en\u00ed v tomto p\u0159\u00edpad\u011b je vytvo\u0159it slu\u017ebu, kter\u00e1 pro ka\u017ed\u00fd po\u017eadavek u\u017eivatele provede v\u0161echny pot\u0159ebn\u00e9 kontroly (autorizace atd.) a pot\u00e9 st\u00e1hne soubor p\u0159\u00edmo z na\u0161eho \u00falo\u017ei\u0161t\u011b. Hlavn\u00ed nev\u00fdhodou takov\u00e9ho p\u0159\u00edstupu je, \u017ee statick\u00fd obsah (a soubor s ur\u010ditou reviz\u00ed je v podstat\u011b statick\u00fd obsah) je distribuov\u00e1n stejn\u00fdm serverem, kter\u00fd obsahuje obchodn\u00ed logiku. M\u00edsto toho je mo\u017en\u00e9 vytvo\u0159it n\u00e1sleduj\u00edc\u00ed sch\u00e9ma:<\/p>\n<p><\/p>\n<ul>\n<li>Server vygeneruje URL pro sta\u017een\u00ed. M\u016f\u017ee m\u00edt form\u00e1t file_id + key, kde key je mini-cyfrov\u00fd podpis, kter\u00fd d\u00e1v\u00e1 pr\u00e1vo na p\u0159\u00edstup k prost\u0159edku na n\u00e1sleduj\u00edc\u00edch 24 hodin.<\/li>\n<li>O soubor se star\u00e1 jednoduch\u00fd nginx s n\u00e1sleduj\u00edc\u00edmi mo\u017enostmi:\n<ul>\n<li>Ulo\u017een\u00ed obsahu do mezipam\u011bti. Vzhledem k tomu, \u017ee tato slu\u017eba m\u016f\u017ee b\u00fdt um\u00edst\u011bna na odd\u011blen\u00e9m serveru, ponechali jsme si prostor do budoucna s mo\u017enost\u00ed ukl\u00e1dat v\u0161echny posledn\u00ed sta\u017een\u00e9 soubory na disku.<\/li>\n<li>Kontrola kl\u00ed\u010de v okam\u017eiku nav\u00e1z\u00e1n\u00ed spojen\u00ed<\/li>\n<\/ul>\n<\/li>\n<li>Voliteln\u011b: streamov\u00e1n\u00ed obsahu. Nap\u0159\u00edklad, pokud ve slu\u017eb\u011b komprimujeme v\u0161echny soubory, m\u016f\u017eeme prov\u00e9st jejich dekompresi p\u0159\u00edmo v tomto modulu. V d\u016fsledku toho: IO operace se prov\u00e1d\u011bj\u00ed tam, kde maj\u00ed nejv\u011bt\u0161\u00ed smysl. Archiv\u00e1tor napsan\u00fd v Jav\u011b bude snadno spot\u0159ebov\u00e1vat nadm\u011brn\u00e9 mno\u017estv\u00ed pam\u011bti, nicm\u00e9n\u011b p\u0159episov\u00e1n\u00ed slu\u017eby s obchodn\u00ed logikou do jazyk\u016f jako Rust\/C++ m\u016f\u017ee uk\u00e1zat tak\u00e9 jako neefektivn\u00ed. V na\u0161em p\u0159\u00edpad\u011b se pou\u017e\u00edvaj\u00ed r\u016fzn\u00e9 procesy (nebo dokonce slu\u017eby), co\u017e umo\u017e\u0148uje efektivn\u011b odd\u011blit obchodn\u00ed logiku a IO operace.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pohodln\u00e9 architektonick\u00e9 vzory\" src=\"\/wp-content\/uploads\/2020\/05\/4dead07d5824938e09b986192ccc8f5e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tento model se nezd\u00e1 b\u00fdt p\u0159\u00edli\u0161 podobn\u00fd distribuci statick\u00e9ho obsahu (proto\u017ee nevys\u00edl\u00e1me cel\u00fd bal\u00ed\u010dek statiky n\u011bkam), av\u0161ak ve skute\u010dnosti takov\u00fd p\u0159\u00edstup se skute\u010dn\u011b zab\u00fdv\u00e1 distribuc\u00ed nem\u011bnn\u00fdch dat. V\u00edce ne\u017e to, tento model lze zobecnit i na jin\u00e9 situace, kdy obsah nen\u00ed pouze statick\u00fd, ale m\u016f\u017ee b\u00fdt reprezentov\u00e1n jako soubor nem\u011bnn\u00fdch a neodstraniteln\u00fdch blok\u016f (i kdy\u017e mohou b\u00fdt p\u0159id\u00e1v\u00e1ny).<\/p>\n<p><\/p>\n<p>Jako dal\u0161\u00ed p\u0159\u00edklad (pro upevn\u011bn\u00ed): pokud jste pracovali s Jenkins\/TeamCity, v\u00edte, \u017ee ob\u011b \u0159e\u0161en\u00ed jsou naps\u00e1na v Jav\u011b. Jsou to Java procesy, kter\u00e9 se zab\u00fdvaj\u00ed jak orchestrac\u00ed build\u016f, tak spr\u00e1vou obsahu. Konkr\u00e9tn\u011b maj\u00ed oba \u00fakoly jako \"p\u0159edat soubor\/slo\u017eku ze serveru\". Nap\u0159\u00edklad: vyd\u00e1n\u00ed artefakt\u016f, p\u0159ed\u00e1n\u00ed zdrojov\u00e9ho k\u00f3du (kdy\u017e agent nestahuje k\u00f3d p\u0159\u00edmo z repozit\u00e1\u0159e, ale server to d\u011bl\u00e1 za n\u011bj), p\u0159\u00edstup k log\u016fm. V\u0161echny tyto \u00fakoly maj\u00ed r\u016fznou z\u00e1t\u011b\u017e na IO. To znamen\u00e1, \u017ee server, kter\u00fd je zodpov\u011bdn\u00fd za slo\u017eitou business logiku, mus\u00ed b\u00fdt schopen efektivn\u011b protla\u010dovat velk\u00e9 datov\u00e9 toky. A co je nejzaj\u00edmav\u011bj\u0161\u00ed, takovou operaci je mo\u017en\u00e9 delegovat na nginx stejn\u00fdm zp\u016fsobem (leda\u017ee bychom do po\u017eadavku m\u011bli p\u0159idat kl\u00ed\u010d dat).<\/p>\n<p><\/p>\n<p>Ale pokud se vr\u00e1t\u00edme k na\u0161emu syst\u00e9mu, dostaneme takovou sch\u00e9ma:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Pohodln\u00e9 architektonick\u00e9 vzory\" src=\"\/wp-content\/uploads\/2020\/05\/97cfbf5daaa6678a9eecc3169692f0fc.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jak je patrn\u00e9, syst\u00e9m se radik\u00e1ln\u011b zkomplikoval. Nyn\u00ed to nen\u00ed jen mini proces, kter\u00fd ukl\u00e1d\u00e1 soubory lok\u00e1ln\u011b. Nyn\u00ed je pot\u0159eba ji\u017e ne zcela jednoduch\u00e1 podpora, kontrola verz\u00ed API atd. Proto, jakmile jsou v\u0161echny diagramy nakresleny, je nejlep\u0161\u00ed podrobn\u011b zhodnotit, zda stoj\u00ed za to investovat do roz\u0161i\u0159itelnosti takov\u00fdch n\u00e1klad\u016f. Pokud v\u0161ak chcete m\u00edt mo\u017enost roz\u0161i\u0159ovat syst\u00e9m (v\u010detn\u011b pr\u00e1ce s je\u0161t\u011b v\u011bt\u0161\u00edm po\u010dtem u\u017eivatel\u016f), budete muset p\u0159istoupit k takov\u00fdm \u0159e\u0161en\u00edm. V\u00fdsledkem je, \u017ee architektura syst\u00e9mu je p\u0159ipravena na zv\u00fd\u0161en\u00ed z\u00e1t\u011b\u017ee (prakticky ka\u017ed\u00fd komponent m\u016f\u017ee b\u00fdt klonov\u00e1n pro horizont\u00e1ln\u00ed \u0161k\u00e1lov\u00e1n\u00ed). Syst\u00e9m lze aktualizovat bez jeho zastaven\u00ed (jen n\u011bkter\u00e9 operace se m\u00edrn\u011b zpomal\u00ed).<\/p>\n<p><\/p>\n<p>Jak u\u017e jsem \u0159\u00edkal na za\u010d\u00e1tku, nyn\u00ed \u0159ada internetov\u00fdch slu\u017eeb za\u010d\u00edn\u00e1 za\u017e\u00edvat zv\u00fd\u0161enou z\u00e1t\u011b\u017e. A n\u011bkter\u00e9 z nich prost\u011b p\u0159estaly spr\u00e1vn\u011b fungovat. V podstat\u011b syst\u00e9my selhaly pr\u00e1v\u011b v okam\u017eiku, kdy by podnik m\u011bl vyd\u011bl\u00e1vat pen\u00edze. To znamen\u00e1, \u017ee m\u00edsto odlo\u017een\u00e9 dod\u00e1vky, m\u00edsto nab\u00eddky klient\u016fm \"pl\u00e1nujte dod\u00e1vku na nejbli\u017e\u0161\u00ed m\u011bs\u00edce\", syst\u00e9m prost\u011b \u0159ekl \"b\u011b\u017ete ke konkurenci\". Vlastn\u011b, to je cena n\u00edzk\u00e9 v\u00fdkonnosti: ztr\u00e1ty nastanou pr\u00e1v\u011b ve chv\u00edli, kdy by zisk byl nejvy\u0161\u0161\u00ed.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Z\u00e1v\u011br<\/h1>\n<p><\/p>\n<p>V\u0161echny tyto p\u0159\u00edstupy byly zn\u00e1my ji\u017e d\u0159\u00edve. Tot\u00e9\u017e VK ji\u017e d\u00e1vno vyu\u017e\u00edv\u00e1 my\u0161lenku Dlouhodob\u00e9ho hostingov\u00e1n\u00ed statick\u00e9ho obsahu pro distribuci obr\u00e1zk\u016f. Mnoho online her vyu\u017e\u00edv\u00e1 sch\u00e9ma Shardingu pro rozd\u011blen\u00ed hr\u00e1\u010d\u016f podle region\u016f nebo pro rozd\u011blen\u00ed hern\u00edch lokalit (pokud je sv\u011bt jednotn\u00fd). P\u0159\u00edstup Event Sourcing se aktivn\u011b pou\u017e\u00edv\u00e1 v elektronick\u00e9 po\u0161t\u011b. V\u011bt\u0161ina aplikac\u00ed obchodn\u00edk\u016f, kde neust\u00e1le p\u0159ich\u00e1zej\u00ed data, je ve skute\u010dnosti postavena na p\u0159\u00edstupu CQRS, aby bylo mo\u017en\u00e9 filtrovat z\u00edskan\u00e1 data. Horizont\u00e1ln\u00ed \u0161k\u00e1lov\u00e1n\u00ed je tak\u00e9 dost dlouho pou\u017e\u00edv\u00e1no v mnoha slu\u017eb\u00e1ch.<\/p>\n<p><\/p>\n<p>Nicm\u00e9n\u011b, co je nejd\u016fle\u017eit\u011bj\u0161\u00ed, v\u0161echny tyto vzory se staly velmi snadno aplikovateln\u00fdmi v modern\u00edch aplikac\u00edch (pokud jsou samoz\u0159ejm\u011b na m\u00edst\u011b). Cloudov\u00e9 slu\u017eby nab\u00edz\u00ed sharding a horizont\u00e1ln\u00ed \u0161k\u00e1lov\u00e1n\u00ed hned, co\u017e je mnohem snaz\u0161\u00ed, ne\u017e samostatn\u011b objedn\u00e1vat r\u016fzn\u00e9 dedikovan\u00e9 servery v r\u016fzn\u00fdch datov\u00fdch centrech. CQRS se stal mnohem jednodu\u0161\u0161\u00edm, alespo\u0148 d\u00edky rozvoji knihoven, jako je RX. P\u0159ed deseti lety mohl jen m\u00e1lokter\u00fd web podporovat n\u011bco takov\u00e9ho. Event sourcing je tak\u00e9 neuv\u011b\u0159iteln\u011b snadno nastaviteln\u00fd d\u00edky ji\u017e hotov\u00fdm kontejner\u016fm s Apache Kafka. P\u0159ed deseti lety by to bylo inovativn\u00ed, nyn\u00ed je to b\u011b\u017en\u00e9. Podobn\u011b i statick\u00e9 hostov\u00e1n\u00ed obsahu: d\u00edky pohodln\u011bj\u0161\u00edm technologi\u00edm (v\u010detn\u011b toho, \u017ee existuje podrobn\u00e1 dokumentace a velk\u00e1 datab\u00e1ze odpov\u011bd\u00ed) se takov\u00fd p\u0159\u00edstup stal je\u0161t\u011b jednodu\u0161\u0161\u00edm.<\/p>\n<p><\/p>\n<p>V\u00fdsledkem je, \u017ee realizace \u0159ady pom\u011brn\u011b slo\u017eit\u00fdch architektonick\u00fdch vzor\u016f se nyn\u00ed stala mnohem jednodu\u0161\u0161\u00ed, co\u017e znamen\u00e1, \u017ee byste se na n\u011b m\u011bli l\u00e9pe p\u0159edem pod\u00edvat. Pokud se v desetilet\u00e9 aplikaci z n\u011bjak\u00e9ho d\u016fvodu vzdali n\u011bkter\u00e9ho z v\u00fd\u0161e uveden\u00fdch \u0159e\u0161en\u00ed kv\u016fli vysok\u00fdm n\u00e1klad\u016fm na zaveden\u00ed a provoz, nyn\u00ed, v nov\u00e9 aplikaci nebo po refaktoringu, m\u016f\u017eete vytvo\u0159it slu\u017ebu, kter\u00e1 bude architektonicky jak roz\u0161i\u0159iteln\u00e1 (z pohledu v\u00fdkonu), tak p\u0159ipraven\u00e1 na nov\u00e9 po\u017eadavky od klient\u016f (nap\u0159\u00edklad pro lokalizaci osobn\u00edch \u00fadaj\u016f).<\/p>\n<p><\/p>\n<p>A co je nejd\u016fle\u017eit\u011bj\u0161\u00ed: pros\u00edm, nepou\u017e\u00edvejte tyto p\u0159\u00edstupy, pokud m\u00e1te jednoduchou aplikaci. Ano, jsou kr\u00e1sn\u00e9 a zaj\u00edmav\u00e9, ale pro web s vrcholovou n\u00e1v\u0161t\u011bvnost\u00ed 100 lid\u00ed se \u010dasto d\u00e1 obej\u00edt s klasick\u00fdm monolitem (alespo\u0148 zven\u010d\u00ed, uvnit\u0159 lze v\u0161e roz\u010dlenit na moduly atd.).<\/p>\n<p>Zdroj: <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.3 - 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\/cs\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"cs_CZ\" \/>\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\/cs\/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\udd47Pohodln\u00e9 architektonick\u00e9 vzory | ProHoster","description":"Ahoj, Habr! Vzhledem k aktu\u00e1ln\u00edm ud\u00e1lostem zp\u016fsoben\u00fdm koronavirem se n\u011bkter\u00e9 internetov\u00e9 slu\u017eby dostaly pod zv\u00fd\u0161en\u00e9 zat\u00ed\u017een\u00ed.","canonical_url":"https:\/\/prohoster.info\/cs\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"cs_CZ","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\/cs\/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\/cs\/wp-json\/wp\/v2\/posts\/80035","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/comments?post=80035"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts\/80035\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media\/80036"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media?parent=80035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/categories?post=80035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/tags?post=80035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}