{"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\/lv\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","title":{"rendered":"\u0112rti arhitekt\u016bras mode\u013ci","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Sveiki, Habr!<\/p>\n<p><\/p>\n<p>Saist\u012bb\u0101 ar pa\u0161reiz\u0113jiem notikumiem, kas saist\u012bti ar koronav\u012brusu, vair\u0101ki interneta pakalpojumi ir sa\u0146\u0113mu\u0161i palielin\u0101tu slodzi. Piem\u0113ram, <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\">viena no tirdzniec\u012bbas \u0137\u0113d\u0113m Apvienotaj\u0101 Karalist\u0113 vienk\u0101r\u0161i apst\u0101din\u0101ja tie\u0161saistes pas\u016bt\u012bjumu vietni,<\/a><\/noindex>, jo jaudu nepietika. Un ne vienm\u0113r ir iesp\u0113jams pa\u0101trin\u0101t serveri, vienk\u0101r\u0161i pievienojot jaud\u012bg\u0101ku aparat\u016bru, tom\u0113r klientu piepras\u012bjumi ir j\u0101apstr\u0101d\u0101 (vai tie aizies pie konkurentiem).<\/p>\n<p><\/p>\n<p>\u0160aj\u0101 rakst\u0101 es \u012bsi past\u0101st\u012b\u0161u par popul\u0101r\u0101m praks\u0113m, kuras \u013caus izveidot \u0101tru un notur\u012bgu pakalpojumu. Tom\u0113r no iesp\u0113jamaj\u0101m izstr\u0101des sh\u0113m\u0101m es izv\u0113l\u0113jos tikai t\u0101s, ar kur\u0101m \u0161obr\u012bd <strong>ir viegli izmantot.<\/strong>Katram punktam jums vai nu ir jau gatavas bibliot\u0113kas, vai iesp\u0113ja atrisin\u0101t uzdevumu, izmantojot m\u0101ko\u0146a platformu.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"gorizontalnoe-masshtabirovanie\">Horizont\u0101l\u0101 m\u0113rogo\u0161ana<\/h1>\n<p><\/p>\n<p>Visvienk\u0101r\u0161\u0101kais un visiem zin\u0101ms punkts. Nosac\u012bti visbie\u017e\u0101k sastopamas divas slodzes sadales sh\u0113mas \u2014 horizont\u0101l\u0101 un vertik\u0101l\u0101 m\u0113rogo\u0161ana. <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\">Pirmaj\u0101 gad\u012bjum\u0101<\/a><\/noindex> j\u016bs \u013caujat pakalpojumiem darboties paral\u0113li, t\u0101d\u0113j\u0101di sadalot slodzi starp tiem. <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\">Otraj\u0101<\/a><\/noindex> j\u016bs pas\u016bt\u0101t jaud\u012bg\u0101kus serverus vai optimiz\u0113jat kodu.<\/p>\n<p><\/p>\n<p>Piem\u0113ram, es pa\u0146em\u0161u abstraktu m\u0101ko\u0146u failu glab\u0101\u0161anu, t\u0101tad noteiktu OwnCloud, OneDrive u.c. analogu.<\/p>\n<p><\/p>\n<p>Standarta att\u0113ls \u0161\u0101das sh\u0113mas apak\u0161\u0101 ir nor\u0101d\u012bts zem\u0101k, tom\u0113r tas tikai demonstr\u0113 sist\u0113mas sare\u017e\u0123\u012bt\u012bbu. Galu gal\u0101 mums ir nepiecie\u0161ams k\u0101d\u0101 veid\u0101 sinhroniz\u0113t pakalpojumus. Kas notiks, ja no plan\u0161etdatora lietot\u0101js saglab\u0101s failu, bet p\u0113c tam v\u0113las to apskat\u012bt ar telefonu?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"\u0112rti arhitekt\u016bras mode\u013ci\" src=\"\/wp-content\/uploads\/2020\/05\/7512c6d8783f5e0a38cc0861b01e54c8.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAt\u0161\u0137ir\u012bba starp pieej\u0101m: vertik\u0101laj\u0101 m\u0113rogo\u0161an\u0101 m\u0113s esam gatavi palielin\u0101t mezglu jaudu, bet horizont\u0101laj\u0101 \u2014 pievienot jaunus mezglus, lai sadal\u012btu slodzi.<\/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> ir diezgan svar\u012bga sh\u0113ma, jo t\u0101 \u013cauj da\u017e\u0101diem klientiem ne tikai piesl\u0113gties da\u017e\u0101diem pakalpojumiem, bet ar\u012b sa\u0146emt vien\u0101dus notikumu pl\u016bsmas. T\u0101s priek\u0161roc\u012bbas nav tik ac\u012bmredzamas vienk\u0101r\u0161ai lietojumprogrammai, tom\u0113r t\u0101s ir \u0101rk\u0101rt\u012bgi svar\u012bgas (un vienk\u0101r\u0161as) slodzes pakalpojumam. T\u0101s b\u016bt\u012bba: ien\u0101ko\u0161aj\u0101m un izejo\u0161aj\u0101m datu pl\u016bsm\u0101m nedr\u012bkst krustoties. Proti, j\u016bs nevarat nos\u016bt\u012bt piepras\u012bjumu un gaid\u012bt atbildi, viet\u0101 tam j\u016bs nos\u016bt\u0101t piepras\u012bjumu pakalpojum\u0101 A, tom\u0113r sa\u0146emat atbildi pakalpojum\u0101 B.<\/p>\n<p><\/p>\n<p>\u0160\u012b pieejas pirm\u0101 priek\u0161roc\u012bba ir iesp\u0113ja p\u0101rtraukt savienojumu (pla\u0161\u0101 noz\u012bm\u0113) ilga piepras\u012bjuma izpildes laik\u0101. Apskat\u012bsim vair\u0101k vai maz\u0101k standarta sec\u012bbu:<\/p>\n<p><\/p>\n<ol>\n<li>Klients nos\u016bt\u012bja piepras\u012bjumu uz serveri.<\/li>\n<li>Serveris uzs\u0101ka garu apstr\u0101di.<\/li>\n<li>Serveris atbild\u0113ja klientam ar rezult\u0101tu.<\/li>\n<\/ol>\n<p><\/p>\n<p>Iedom\u0101simies, ka 2. punkt\u0101 notika savienojuma p\u0101rtraukums (vai nu t\u012bkls p\u0101rsl\u0113dz\u0101s, vai lietot\u0101js p\u0101rg\u0101ja uz citu lapu, p\u0101rtraucot savienojumu). \u0160aj\u0101 gad\u012bjum\u0101 serverim b\u016bs gr\u016bti nos\u016bt\u012bt atbildi lietot\u0101jam ar inform\u0101ciju par to, kas tie\u0161i tika apstr\u0101d\u0101ts. Izmantojot CQRS, sec\u012bba b\u016bs nedaudz at\u0161\u0137ir\u012bga:<\/p>\n<p><\/p>\n<ol>\n<li>Klients pierakst\u012bj\u0101s uz atjaunin\u0101jumiem.<\/li>\n<li>Klients nos\u016bt\u012bja piepras\u012bjumu uz serveri.<\/li>\n<li>Serveris atbild\u0113ja: \"piepras\u012bjums pie\u0146emts\".<\/li>\n<li>Serveris atbild\u0113ja ar rezult\u0101tu caur kan\u0101lu no punkta \"1\".<\/li>\n<\/ol>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"\u0112rti arhitekt\u016bras mode\u013ci\" src=\"\/wp-content\/uploads\/2020\/05\/8a00ea93eecc7cc0754122857c5f90d0.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>K\u0101 redzams, sh\u0113ma ir nedaudz sare\u017e\u0123\u012bt\u0101ka. Vair\u0101k nek\u0101 tam, intuit\u012bv\u0101 pieeja piepras\u012bjums-atbilde \u0161eit nav kl\u0101teso\u0161a. Tom\u0113r k\u0101 redzams, savienojuma p\u0101rtraukums piepras\u012bjuma apstr\u0101des laik\u0101 nenoved\u012bs pie k\u013c\u016bdas. Turkl\u0101t, ja lietot\u0101js patie\u0161\u0101m ir savienots ar pakalpojumu no vair\u0101kiem ier\u012bc\u0113m (piem\u0113ram, no mobil\u0101 telefona un plan\u0161etes), ir iesp\u0113jams pan\u0101kt, ka atbilde tiek sa\u0146emta uz ab\u0101m ier\u012bc\u0113m.<\/p>\n<p><\/p>\n<p>Interesanti, ka ien\u0101ko\u0161o zi\u0146ojumu apstr\u0101des kods k\u013c\u016bst l\u012bdz\u012bgs (ne uz 100%) gan tiem notikumiem, uz kuriem ietekm\u0113ja pats klients, gan citiem notikumiem, tostarp no citiem klientiem.<\/p>\n<p><\/p>\n<p>Tom\u0113r realit\u0101t\u0113 m\u0113s ieg\u016bstam papildu priek\u0161roc\u012bbas, jo vienvirziena pl\u016bsmu var apstr\u0101d\u0101t funkcion\u0101laj\u0101 stil\u0101 (izmantojot RX un analogus). Un tas ir nopietns pluss, jo b\u016bt\u012bb\u0101 lietojumprogrammu var izveidot piln\u012bgi reakt\u012bvu, izmantojot v\u0113l funkcion\u0101lo pieeju. Lieliem projektiem tas var b\u016btiski ietaup\u012bt resursus izstr\u0101d\u0113 un atbalst\u0101.<\/p>\n<p><\/p>\n<p>Ja apvieno \u0161o pieeju ar horizont\u0101lu m\u0113rogojam\u012bbu, tad bonus\u0101 m\u0113s ieg\u016bstam iesp\u0113ju nos\u016bt\u012bt piepras\u012bjumus uz vienu serveri, bet sa\u0146emt atbildes no cita. T\u0101d\u0113j\u0101di klients var pats izv\u0113l\u0113ties sev \u0113rtu pakalpojumu, bet sist\u0113ma iek\u0161pus\u0113 tom\u0113r sp\u0113s pareizi apstr\u0101d\u0101t notikumus.<\/p>\n<p><\/p>\n<h1 id=\"event-sourcing\">Notikumu avotu<\/h1>\n<p><\/p>\n<p>K\u0101 j\u016bs zin\u0101t, viena no galvenaj\u0101m izplat\u012bto sist\u0113mu \u012bpa\u0161\u012bb\u0101m ir kop\u012bga laika un kop\u012bgas kritisk\u0101s sekcijas tr\u016bkums. Vienam procesam varat veikt sinhroniz\u0101ciju (uz to pa\u0161u mutex), iek\u0161\u0101 kur\u0101 esat p\u0101rliecin\u0101ts, ka neviens cits neizpilda \u0161o kodu. Tom\u0113r izplat\u012btai sist\u0113mai tas ir b\u012bstami, jo tam b\u016bs nepiecie\u0161ami papildu izdevumi, k\u0101 ar\u012b tiks zaud\u0113ta visa m\u0113rogo\u0161anas pievilc\u012bba \u2014 tom\u0113r visi komponenti gaid\u012bs vienu.<\/p>\n<p><\/p>\n<p>No t\u0101 ieg\u016bstam svar\u012bgu faktu \u2014 \u0101tru izplat\u012btu sist\u0113mu nevar sinhroniz\u0113t, jo tad m\u0113s samazin\u0101sim veiktsp\u0113ju. No otras puses, bie\u017ei vien mums nepiecie\u0161ama noteikta komponentu saska\u0146ot\u012bba. Un tam var izmantot pieeju ar <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>, kur tiek garant\u0113ts, ka datos neizmai\u0146u gad\u012bjum\u0101 p\u0113c k\u0101da laika p\u0113c p\u0113d\u0113j\u0101s atjaunin\u0101\u0161anas (\u201cgalu gal\u0101\u201d) visas piepras\u012bjumi atgriez\u012bs p\u0113d\u0113jo atjaunin\u0101to v\u0113rt\u012bbu.<\/p>\n<p><\/p>\n<p>Ir svar\u012bgi saprast, ka klasisk\u0101m datu b\u0101z\u0113m bie\u017ei tiek izmantota <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Consistency_model#Strict_consistency\">stingra saska\u0146ot\u012bba<\/a><\/noindex>, kur katram mezglam ir vien\u0101da inform\u0101cija (\u0161\u0101du parasti sasniedz, ja dar\u012bjums tiek uzskat\u012bts par izveidotu tikai p\u0113c otr\u0101 servera atbildes). \u0160eit ir da\u017ei atvieglojumi d\u0113\u013c izol\u0101cijas l\u012bme\u0146iem, tom\u0113r kop\u0113j\u0101 b\u016bt\u012bba paliek nemain\u012bga \u2014 j\u016bs varat dz\u012bvot piln\u012bgi saska\u0146ot\u0101 pasaul\u0113.<\/p>\n<p><\/p>\n<p>Tom\u0113r atgriez\u012bsimies pie s\u0101kotn\u0113j\u0101s uzdevuma. Ja da\u013ca sist\u0113mas var tikt uzb\u016bv\u0113ta ar <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventual consistency<\/a><\/noindex>, tad var uzb\u016bv\u0113t n\u0101kamo sh\u0113mu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"\u0112rti arhitekt\u016bras mode\u013ci\" src=\"\/wp-content\/uploads\/2020\/05\/33c80be6bc33bd897ca9b9e5525f9ae8.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Svar\u012bgas \u0161\u012b pieejas iez\u012bmes:<\/p>\n<p><\/p>\n<ul>\n<li>Katrs ien\u0101ko\u0161ais piepras\u012bjums tiek ievietots vien\u0101 rind\u0101.<\/li>\n<li>Apmekl\u0113jot piepras\u012bjumu, pakalpojums var ar\u012b ievietot uzdevumus cit\u0101s rind\u0101s.<\/li>\n<li>Katram ien\u0101ko\u0161ajam notikumam ir identifikators (kas nepiecie\u0161ams dublik\u0101tu no\u0146em\u0161anai).<\/li>\n<li>Rinda ideolo\u0123iski darbojas p\u0113c \"pievienot tikai\" sh\u0113mas. No t\u0101s nevar iz\u0146emt elementus vai tos p\u0101rvietot.<\/li>\n<li>Rinda darbojas p\u0113c FIFO sh\u0113mas (atvainojiet par tautolo\u0123iju). Ja nepiecie\u0161ams veikt paral\u0113lu izpildi, tad j\u0101veic objekti cit\u0101s rind\u0101s vien\u0101 no posmiem.<\/li>\n<\/ul>\n<p><\/p>\n<p>Atg\u0101dinu, ka m\u0113s izskat\u0101m tie\u0161saistes failu glab\u0101\u0161anas gad\u012bjumu. \u0160\u0101d\u0101 gad\u012bjum\u0101 sist\u0113ma izskat\u012bsies apm\u0113ram t\u0101:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"\u0112rti arhitekt\u016bras mode\u013ci\" src=\"\/wp-content\/uploads\/2020\/05\/b95efb29545dcde1db9432d12d00a1b1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ir svar\u012bgi, ka diagramm\u0101 redzamie pakalpojumi ne vienm\u0113r apz\u012bm\u0113 atsevi\u0161\u0137u serveri. Pat process var b\u016bt viens un tas pats. Svar\u012bg\u0101ks ir cits jaut\u0101jums: ideolo\u0123iski \u0161\u012bs lietas ir sadal\u012btas t\u0101, lai b\u016btu viegli pielietot horizont\u0101lo m\u0113rogo\u0161anu.<\/p>\n<p><\/p>\n<p>Un diviem lietot\u0101jiem sh\u0113ma izskat\u012bsies \u0161\u0101di (pakalpojumi, kas paredz\u0113ti da\u017e\u0101diem lietot\u0101jiem, ir apz\u012bm\u0113ti ar da\u017e\u0101d\u0101m kr\u0101s\u0101m):<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"\u0112rti arhitekt\u016bras mode\u013ci\" src=\"\/wp-content\/uploads\/2020\/05\/4c4aadc8b9dd505c3ad743e69fee4fae.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Bonusi no t\u0101das kombin\u0101cijas:<\/p>\n<p><\/p>\n<ul>\n<li>Inform\u0101cijas apstr\u0101des pakalpojumi ir sadal\u012bti. Rindas ar\u012b ir sadal\u012btas. Ja mums nepiecie\u0161ams palielin\u0101t sist\u0113mas caurlaidsp\u0113ju, mums tikai j\u0101palai\u017e vair\u0101k pakalpojumu uz liel\u0101ka skaita serveriem.<\/li>\n<li>Kad m\u0113s sa\u0146emam inform\u0101ciju no lietot\u0101ja, mums nav oblig\u0101ti j\u0101gaida piln\u012bga datu saglab\u0101\u0161ana. Glu\u017ei pret\u0113ji, mums ir pietiekami atbild\u0113t \"labi\", un p\u0113c tam pak\u0101peniski uzs\u0101kt darbu. Rinda t\u0101d\u0113j\u0101di izl\u012bdzina p\u0113k\u0161\u0146as pieauguma, jo jauna objekta pievieno\u0161ana notiek \u0101tri, un lietot\u0101jam nav j\u0101gaida, lai nost\u0101tos pie visa cikla.<\/li>\n<li>Piem\u0113ram, es pievienoju datu deduplication pakalpojumu, kas cen\u0161as apvienot vien\u0101dus failus. Ja tas ilgsto\u0161i darbojas 1% gad\u012bjumu, klients to praktiski nenov\u0113ros (skat. iepriek\u0161), kas ir liels plus, jo m\u0113s vairs nepras\u0101m simtprocent\u012bgu \u0101trumu un uzticam\u012bbu.<\/li>\n<\/ul>\n<p><\/p>\n<p>Tom\u0113r t\u016bl\u012bt ir redzami ar\u012b tr\u016bkumi:<\/p>\n<p><\/p>\n<ul>\n<li>M\u016bsu sist\u0113m\u0101 ir zudusi stingra konsekvence. Tas noz\u012bm\u0113, ka, piem\u0113ram, piesakoties da\u017e\u0101diem pakalpojumiem, teor\u0113tiski var izn\u0101kt at\u0161\u0137ir\u012bgs st\u0101voklis (jo viens no pakalpojumiem var nesagaid\u012bt pazi\u0146ojumu no iek\u0161\u0113j\u0101s rindas). K\u0101 v\u0113l viena sekas, sist\u0113m\u0101 vairs nav kop\u012bga laika. T\u0101tad, piem\u0113ram, nevar vienk\u0101r\u0161i sak\u0101rtot visus notikumus p\u0113c to iera\u0161an\u0101s laika, jo starp serveriem pulkste\u0146i var neb\u016bt sinhroniz\u0113ti (turkl\u0101t, identisks laiks diviem serveriem ir utopija).<\/li>\n<li>Nav iesp\u0113jams vienk\u0101r\u0161i atgriezt iepriek\u0161\u0113jos notikumus (k\u0101 to var\u0113tu izdar\u012bt ar datu b\u0101zi). T\u0101 viet\u0101 ir nepiecie\u0161ams pievienot jaunu notikumu \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/49451237\/compensating-events-on-cqrs-es-architecture\">compensation event<\/a><\/noindex>, kas main\u012bs p\u0113d\u0113jo st\u0101vokli uz nepiecie\u0161amo. K\u0101 piem\u0113rs no l\u012bdz\u012bgas jomas: bez v\u0113stures p\u0101rrakst\u012b\u0161anas (kas da\u017eos gad\u012bjumos ir slikti) git nevar atgriezt komanda, tom\u0113r var veikt \u012bpa\u0161u <noindex><a rel=\"nofollow\" href=\"https:\/\/git-scm.com\/docs\/git-revert\">rollback commit<\/a><\/noindex>, kas paties\u012bb\u0101 vienk\u0101r\u0161i atgriez\u012bs veco st\u0101vokli. Tom\u0113r v\u0113stur\u0113 paliks gan k\u013c\u016bdains komits, gan rollback.<\/li>\n<li>Datu sh\u0113ma var main\u012bties no izlaiduma l\u012bdz izlaidumam, ta\u010du vecos notikumus vairs nevar atjaunin\u0101t uz jauno standartu (jo notikumus b\u016bt\u012bb\u0101 nevar main\u012bt).<\/li>\n<\/ul>\n<p><\/p>\n<p>K\u0101 redzams, Event Sourcing lieliski sader ar CQRS. Turkl\u0101t izveidot sist\u0113mu ar efekt\u012bv\u0101m un \u0113rt\u0101m rind\u0101m, bet bez datu pl\u016bsmu dal\u012b\u0161anas, jau pa\u0161\u0101 b\u016bt\u012bb\u0101 ir gr\u016bti, jo b\u016bs j\u0101pievieno sinhroniz\u0101cijas punkti, kas izn\u012bcin\u0101s visu pozit\u012bvo efektu no rind\u0101m. Lietojot abus pieejas vienlaic\u012bgi, nepiecie\u0161ams nedaudz kori\u0123\u0113t programmas darba kodu. M\u016bsu gad\u012bjum\u0101, nos\u016btot failu uz serveri, atbild\u0113 sa\u0146emam tikai \"ok\", kas noz\u012bm\u0113 tikai to, ka \"faila pievieno\u0161anas oper\u0101cija ir saglab\u0101ta\". Form\u0101li tas nenoz\u012bm\u0113, ka dati jau ir pieejami cit\u0101s ier\u012bc\u0113s (piem\u0113ram, deduplic\u0113\u0161anas pakalpojums var p\u0101rveidot indeksu). Tom\u0113r p\u0113c k\u0101da laika klients sa\u0146ems pazi\u0146ojumu stil\u0101 \"failu X ir saglab\u0101ts\".<\/p>\n<p><\/p>\n<p>K\u0101 rezult\u0101t\u0101:<\/p>\n<p><\/p>\n<ul>\n<li>Fails s\u016btot statusu skaits pieaug: viet\u0101 klasisk\u0101 \"fails nos\u016bt\u012bts\" m\u0113s sa\u0146emam divus: \"fails pievienots rind\u0101 server\u012b\" un \"fails saglab\u0101ts glab\u0101tuv\u0113\". P\u0113d\u0113jais noz\u012bm\u0113, ka citas ier\u012bces jau var s\u0101kt sa\u0146emt failu (\u0146emot v\u0113r\u0101, ka rindas darbojas ar at\u0161\u0137ir\u012bgu \u0101trumu).<\/li>\n<li>\u0145emot v\u0113r\u0101, ka inform\u0101cija par nos\u016bt\u012b\u0161anu tagad n\u0101k pa da\u017e\u0101diem kan\u0101liem, mums ir nepiecie\u0161ams izstr\u0101d\u0101t risin\u0101jumus, lai sa\u0146emtu faila apstr\u0101des statusu. K\u0101 rezult\u0101ts: at\u0161\u0137ir\u012bb\u0101 no klasisk\u0101 request-response, klients var tikt restart\u0113ts faila apstr\u0101des laik\u0101, tom\u0113r \u0161\u012bs apstr\u0101des statuss b\u016bs pareizs. Un \u0161is punkts darbojas b\u016bt\u012bb\u0101 autom\u0101tiski. T\u0101d\u0113j\u0101di: m\u0113s tagad esam tolerant\u0101ki pret k\u013c\u016bd\u0101m.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sharding\">Sharding<\/h1>\n<p><\/p>\n<p>K\u0101 jau min\u0113ts iepriek\u0161, sist\u0113m\u0101s ar notikumu avotu stingra saska\u0146ot\u012bba neeksist\u0113. Tas noz\u012bm\u0113, ka m\u0113s varam izmantot vair\u0101kus glab\u0101\u0161anas veidus bez jebk\u0101das sinhroniz\u0101cijas starp tiem. Tuvojoties m\u016bsu uzdevumam, m\u0113s varam:<\/p>\n<p><\/p>\n<ul>\n<li>Sadal\u012bt failus p\u0113c veidiem. Piem\u0113ram, att\u0113lus\/video var dekod\u0113t un izv\u0113l\u0113ties efekt\u012bv\u0101ku form\u0101tu.<\/li>\n<li>Dal\u012bt kontus pa valst\u012bm. \u0145emot v\u0113r\u0101 daudzas likumdo\u0161anas pras\u012bbas, \u0161\u0101da iesp\u0113ja var b\u016bt nepiecie\u0161ama, ta\u010du \u0161\u012b arhitekt\u016bras sh\u0113ma nodro\u0161ina autom\u0101tisku \u0161\u0101dus risin\u0101jumus.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"\u0112rti arhitekt\u016bras mode\u013ci\" src=\"\/wp-content\/uploads\/2020\/05\/dd310df700bc39c014d0105a3425fece.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ja v\u0113laties p\u0101rvietot datus no viena kr\u0101tuves uz citu, tad \u0161eit p\u0113c noklus\u0113juma nestr\u0101d\u0101s standarta metodes. Diem\u017e\u0113l \u0161aj\u0101 gad\u012bjum\u0101 ir nepiecie\u0161ams aptur\u0113t rindu, veikt migr\u0101ciju un p\u0113c tam to ats\u0101kt. Parasti datus nav iesp\u0113jams p\u0101rvietot 'uz lido', ta\u010du, ja notikumu rinda tiek piln\u012bb\u0101 saglab\u0101ta un jums ir iepriek\u0161\u0113jo st\u0101vok\u013cu kopijas, tad m\u0113s varam p\u0101rsp\u0113l\u0113t notikumus \u0161\u0101d\u0101 veid\u0101:<\/p>\n<p><\/p>\n<ul>\n<li>Katram notikumam Event Source ir savu identifikatoru (ide\u0101l\u0101 gad\u012bjum\u0101 \u2014 ne samazino\u0161u). T\u0101d\u0113j\u0101di kr\u0101tuv\u0113 varam pievienot lauku \u2014 p\u0113d\u0113j\u0101 apstr\u0101d\u0101t\u0101 elementa id.<\/li>\n<li>Dubl\u0113jam rindu, lai visi notikumi var\u0113tu tikt apstr\u0101d\u0101ti vair\u0101kiem neatkar\u012bgiem kr\u0101tuves veidiem (pirmais \u2014 tas, kur jau \u0161obr\u012bd tiek glab\u0101ti dati, bet otrais \u2014 jauns, kas \u0161obr\u012bd ir tuk\u0161s). Otr\u0101 rinda, protams, \u0161obr\u012bd netiek apstr\u0101d\u0101ta.<\/li>\n<li>S\u0101kam otro rindu (t.i., s\u0101kam p\u0101rsp\u0113l\u0113t notikumus).<\/li>\n<li>Kad jaun\u0101 rinda b\u016bs sal\u012bdzino\u0161i tuk\u0161a (t.i., vid\u0113j\u0101 laika at\u0161\u0137ir\u012bba starp elementa pievieno\u0161anu un t\u0101 izvilk\u0161anu b\u016bs pie\u0146emama), var s\u0101kt p\u0101rsl\u0113gt las\u012bt\u0101jus uz jauno kr\u0101tuvi.<\/li>\n<\/ul>\n<p><\/p>\n<p>K\u0101 redzams, m\u016bsu sist\u0113m\u0101 nekad nav bijusi stingra saska\u0146ot\u012bba. Ir tikai beigu saska\u0146ot\u012bba, t.i., garantija, ka notikumi tiek apstr\u0101d\u0101ti taj\u0101 pa\u0161\u0101 sec\u012bb\u0101 (ta\u010du ar da\u017e\u0101du aizturi). Izmantojot to, m\u0113s sal\u012bdzino\u0161i viegli varam p\u0101rvietot datus bez sist\u0113mas apst\u0101\u0161an\u0101s uz otras pasaules pusi.<\/p>\n<p><\/p>\n<p>T\u0101d\u0113j\u0101di, turpinot m\u016bsu piem\u0113ru par tie\u0161saistes kr\u0101tuvi failiem, \u0161\u0101da arhitekt\u016bra jau pied\u0101v\u0101 mums vair\u0101kus ieguvumus:<\/p>\n<p><\/p>\n<ul>\n<li>M\u0113s varam p\u0101rvietot objektus tuv\u0101k lietot\u0101jiem, un t\u0101d\u0113j\u0101di dinamiski uzlabot servisa kvalit\u0101ti. <\/li>\n<li>M\u0113s varam glab\u0101t da\u013cu datu iek\u0161\u0113j\u0101s komp\u0101nij\u0101s. Piem\u0113ram, Enterprise lietot\u0101ji bie\u017ei pieprasa, lai vi\u0146u dati tiktu glab\u0101ti kontrol\u0113tos datu centros (lai izvair\u012btos no datu nopl\u016bd\u0113m). Pateicoties sharding, m\u0113s varam viegli atbalst\u012bt \u0161o pras\u012bbu. Uzdevums v\u0113l vair\u0101k vienk\u0101r\u0161ojas, ja pas\u016bt\u012bt\u0101jam ir sader\u012bga m\u0101ko\u0146a infrastrukt\u016bra (piem\u0113ram, <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>Un svar\u012bg\u0101kais ir tas, ka mums to nevajag dar\u012bt. S\u0101kum\u0101 mums piln\u012bb\u0101 pietiktu ar vienu kr\u0101tuvi visiem kontiem (lai \u0101tr\u0101k s\u0101ktu str\u0101d\u0101t). Un \u0161\u012bs sist\u0113mas galven\u0101 iez\u012bme ir t\u0101, ka, lai gan t\u0101 ir papla\u0161in\u0101ma, s\u0101kotn\u0113j\u0101 posm\u0101 t\u0101 ir pietiekami vienk\u0101r\u0161a. Vienk\u0101r\u0161i nav nepiecie\u0161ams uzreiz rakst\u012bt kodu, kas darbojas ar miljonu atsevi\u0161\u0137u neatkar\u012bgu rind\u0101m utt. Ja b\u016bs nepiecie\u0161ams, to var izdar\u012bt n\u0101kotn\u0113.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"static-content-hosting\">Statisk\u0101 satura mitin\u0101\u0161ana<\/h1>\n<p><\/p>\n<p>\u0160is punkts var \u0161\u0137ist pavisam ac\u012bmredzams, tom\u0113r tas ir nepiecie\u0161ams vismaz pusl\u012bdz standartiz\u0113tai noslogotai lietojumprogrammai. T\u0101s b\u016bt\u012bba ir vienk\u0101r\u0161a: viss statiskais saturs tiek pieg\u0101d\u0101ts ne no t\u0101 pa\u0161a servera, kur atrodas lietojumprogramma, bet no \u012bpa\u0161iem serveriem, kas speci\u0101li paredz\u0113ti \u0161im nol\u016bkam. T\u0101d\u0113j\u0101di \u0161ie darbi tiek veikti \u0101tr\u0101k (nosac\u012bts nginx pieg\u0101d\u0101 failus \u0101tr\u0101k un l\u0113t\u0101k nek\u0101 Java serveris). Plus, CDN arhitekt\u016bra (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Content_delivery_network\">Satura pieg\u0101des t\u012bkls<\/a><\/noindex>) \u013cauj izvietot m\u016bsu failus tuv\u0101k galalietot\u0101jiem, kas pozit\u012bvi ietekm\u0113 pakalpojuma lieto\u0161anas \u0113rtumu.<\/p>\n<p><\/p>\n<p>Vienk\u0101r\u0161\u0101kais un standartiz\u0113t\u0101kais statisk\u0101 satura piem\u0113rs ir skriptu un att\u0113lu kopums vietnei. Ar tiem viss ir vienk\u0101r\u0161i \u2014 tie tiek iepriek\u0161 zin\u0101mi, tad arh\u012bvs tiek aug\u0161upiel\u0101d\u0113ts uz CDN serveriem, no kuriem tas tiek pieg\u0101d\u0101ts galalietot\u0101jiem.<\/p>\n<p><\/p>\n<p>Tom\u0113r praks\u0113 statiskajam saturam var piem\u0113rot pieeju, kas ir l\u012bdz\u012bga lambda arhitekt\u016brai. Atgrie\u017eamies pie m\u016bsu uzdevuma (interneta failu kr\u0101tuve), kur mums nepiecie\u0161ams pieg\u0101d\u0101t failus lietot\u0101jiem. Vienk\u0101r\u0161\u0101kais risin\u0101jums ir izveidot pakalpojumu, kas katram lietot\u0101ja piepras\u012bjumam veic visas nepiecie\u0161am\u0101s p\u0101rbaudes (autoriz\u0101cija u.t.t.), un p\u0113c tam lejupiel\u0101d\u0113 failu tie\u0161i no m\u016bsu kr\u0101tuves. Galven\u0101 \u0161\u0101da pieejas m\u012bnuss ir tas, ka statiskais saturs (un fails ar noteiktu rev\u012bziju faktiski ir statisks saturs) tiek pieg\u0101d\u0101ts no t\u0101 pa\u0161a servera, kur\u0101 ir biznesa lo\u0123ika. T\u0101 viet\u0101 var izveidot \u0161\u0101du sh\u0113mu:<\/p>\n<p><\/p>\n<ul>\n<li>Serveris izsniedz URL faila lejupiel\u0101dei. Tam var b\u016bt forma file_id + key, kur key ir mazs ciparu paraksts, kas sniedz ties\u012bbas piek\u013c\u016btu resursam tuv\u0101k\u0101s diennakts laik\u0101.<\/li>\n<li>Faila pieg\u0101di nodro\u0161ina vienk\u0101r\u0161s nginx ar \u0161\u0101d\u0101m opcij\u0101m:\n<ul>\n<li>Satura\u0161ana ar saturu. T\u0101 k\u0101 \u0161is pakalpojums var atrasties uz atsevi\u0161\u0137a servera, m\u0113s esam atst\u0101ju\u0161i iesp\u0113ju n\u0101kotnei saglab\u0101t visus jaun\u0101kos lejupiel\u0101d\u0113tos failus disk\u0101.<\/li>\n<li>Atsl\u0113gas p\u0101rbaude savienojuma izveides br\u012bd\u012b<\/li>\n<\/ul>\n<\/li>\n<li>Papildus: satura straum\u0113\u0161ana. Piem\u0113ram, ja m\u0113s saspringstam visus failus pakalpojum\u0101, tad var veikt izsai\u0146o\u0161anu tie\u0161i \u0161aj\u0101 modul\u012b. T\u0101d\u0113j\u0101di: IO oper\u0101cijas tiek veiktas tur, kur t\u0101m ir visvair\u0101k vietas. Java arhivators var viegli pat\u0113r\u0113t daudz liekas atmi\u0146as, tom\u0113r p\u0101rveidot pakalpojumu ar biznesa lo\u0123iku uz Rust\/C++ var b\u016bt ar\u012b neefekt\u012bvi. M\u016bsu gad\u012bjum\u0101 tiek izmantoti da\u017e\u0101di procesi (vai pat pakalpojumi), t\u0101p\u0113c biznesa lo\u0123iku un IO oper\u0101cijas var efekt\u012bvi no\u0161\u0137irt.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"\u0112rti arhitekt\u016bras mode\u013ci\" src=\"\/wp-content\/uploads\/2020\/05\/4dead07d5824938e09b986192ccc8f5e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0160\u0101da sh\u0113ma neizskat\u0101s l\u012bdz\u012bga statiska satura izplat\u012b\u0161anai (jo m\u0113s neko neizlai\u017eam uz citu statisk\u0101 satura paketi), tom\u0113r paties\u012bb\u0101 \u0161\u0101da pieeja piev\u0113r\u0161as nemain\u012bgu datu izplat\u012b\u0161anai. Vair\u0101k nek\u0101 tas, \u0161o sh\u0113mu var visp\u0101rin\u0101t ar\u012b uz cit\u0101m situ\u0101cij\u0101m, kad saturs nav tikai statisks, bet to var att\u0113lot k\u0101 nemain\u012bgu un neizdz\u0113\u0161amu bloku kopumu (lai gan tos var pievienot).<\/p>\n<p><\/p>\n<p>K\u0101 v\u0113l viens piem\u0113rs (lai nostiprin\u0101tu): ja esat str\u0101d\u0101jis ar Jenkins\/TeamCity, tad zin\u0101t, ka abas risin\u0101jumi ir rakst\u012bti Java. Abi tie ir Java procesi, kas nodarbojas gan ar b\u016bvju or\u0137estr\u0101ciju, gan saturu p\u0101rvald\u012bbu. \u012apa\u0161i, abiem ir uzdevumi, piem\u0113ram, \"p\u0101rnest failu\/mapi no servera\". Piem\u0113ram: artefaktu izsnieg\u0161ana, avota koda p\u0101rs\u016bt\u012b\u0161ana (ja a\u0123ents nepie\u0146em kodu tie\u0161i no re\u0123istra, bet to dara servers), piek\u013cuve \u017eurn\u0101liem. Visus \u0161os uzdevumus raksturo I\/O slodze. T\u0101d\u0113j\u0101di izr\u0101d\u0101s, ka serverim, kas atbild par sare\u017e\u0123\u012btu biznesa lo\u0123iku, vienlaikus j\u0101sp\u0113j efekt\u012bvi caur sevi virz\u012bt lielus datu pl\u016bsmus. Un kas ir visinteresant\u0101kais, l\u012bdz\u012bgu oper\u0101ciju var dele\u0123\u0113t tam pa\u0161am nginx tie\u0161i p\u0113c t\u0101s pa\u0161as sh\u0113mas (iz\u0146emot to, ka piepras\u012bjum\u0101 j\u0101iek\u013cauj datu atsl\u0113ga).<\/p>\n<p><\/p>\n<p>Tom\u0113r, ja atgrie\u017eamies pie m\u016bsu sist\u0113mas, m\u0113s redzam \u0161\u0101du sh\u0113mu:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"\u0112rti arhitekt\u016bras mode\u013ci\" src=\"\/wp-content\/uploads\/2020\/05\/97cfbf5daaa6678a9eecc3169692f0fc.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>K\u0101 redzams, sist\u0113ma ir radik\u0101li sare\u017e\u0123\u012bjusies. Tagad t\u0101 vairs nav vienk\u0101r\u0161a mini-process, kas glab\u0101 failus lok\u0101li. Tagad ir nepiecie\u0161ama jau ne t\u0101 vienk\u0101r\u0161\u0101k\u0101 atbalsta, API versiju kontroles utt. T\u0101p\u0113c, kad visas diagrammas ir uzz\u012bm\u0113tas, vislab\u0101k ir detaliz\u0113ti nov\u0113rt\u0113t, vai \u0161\u012bs papla\u0161in\u0101m\u012bbas izmaksas ir pamatotas. Ta\u010du, ja v\u0113laties sp\u0113t papla\u0161in\u0101t sist\u0113mu (tai skait\u0101, str\u0101d\u0101jot ar v\u0113l liel\u0101ku lietot\u0101ju skaitu), tad b\u016bs j\u0101izdara \u0161\u0101di risin\u0101jumi. Toties, k\u0101 rezult\u0101t\u0101, sist\u0113mas arhitekt\u016bra ir gatava slodzes palielin\u0101\u0161anai (praktiski katru komponentu var klon\u0113t horizont\u0101lai m\u0113rogo\u0161anai). Sist\u0113mu var atjaunin\u0101t, nep\u0101rtraucot to (vienk\u0101r\u0161i da\u017eas darb\u012bbas nedaudz pal\u0113nin\u0101s).<\/p>\n<p><\/p>\n<p>K\u0101 es jau teicu pa\u0161\u0101 s\u0101kum\u0101, \u0161obr\u012bd da\u017ei interneta pakalpojumi ir s\u0101ku\u0161i sa\u0146emt palielin\u0101tu slodzi. Un da\u017ei no tiem vienk\u0101r\u0161i ir p\u0101rst\u0101ju\u0161i str\u0101d\u0101t pareizi. Paties\u012bb\u0101 sist\u0113mas atteic\u0101s tie\u0161i taj\u0101 br\u012bd\u012b, kad uz\u0146\u0113mumam vajadz\u0113tu peln\u012bt naudu. T\u0101tad, viet\u0101, lai atliktu pieg\u0101di, viet\u0101, lai pied\u0101v\u0101tu klientiem 'pl\u0101nojiet pieg\u0101di tuv\u0101kajiem m\u0113ne\u0161iem', sist\u0113ma vienk\u0101r\u0161i teica 'dodieties pie konkurentiem'. Faktiski, t\u0101 ir zemas veiktsp\u0113jas cena: zaud\u0113jumi notiks tie\u0161i tad, kad pe\u013c\u0146a b\u016btu visaugst\u0101k\u0101.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Secin\u0101jums<\/h1>\n<p><\/p>\n<p>Visi \u0161ie pieejas jau bija zin\u0101mas iepriek\u0161. Tas pats VK jau sen izmanto Static Content Hosting ideju att\u0113lu izsnieg\u0161anai. Daudzas tie\u0161saistes sp\u0113les izmanto Sharding sh\u0113mu sp\u0113l\u0113t\u0101ju sadal\u012b\u0161anai pa re\u0123ioniem vai ar\u012b sp\u0113\u013cu lok\u0101ciju sadal\u012b\u0161anai (ja pats pasaule ir vienota). Event Sourcing pieeja tiek akt\u012bvi izmantota elektroniskaj\u0101 pasta sist\u0113m\u0101. Liel\u0101k\u0101 da\u013ca tirgot\u0101ju lietojumprogrammu, kur\u0101s nep\u0101rtraukti ien\u0101k dati, paties\u012bb\u0101 ir b\u016bv\u0113tas uz CQRS pieejas, lai sp\u0113tu filtr\u0113t sa\u0146emto inform\u0101ciju. Un horizont\u0101la m\u0113rogo\u0161ana jau gadu desmitiem tiek izmantota daudzu pakalpojumu nodro\u0161in\u0101\u0161an\u0101.<\/p>\n<p><\/p>\n<p>Tom\u0113r vissvar\u012bg\u0101kais ir tas, ka \u0161os mode\u013cus tagad ir \u013coti viegli piem\u0113rot m\u016bsdienu lietojumprogramm\u0101s (ja t\u0101s ir piem\u0113rotas, protams). M\u0101ko\u0146i pied\u0101v\u0101 sharding un horizont\u0101lu m\u0113rogo\u0161anu uzreiz, kas ir daudz viegl\u0101k nek\u0101 pas\u016bt\u012bt da\u017e\u0101dus velt\u012btus serverus da\u017e\u0101dos datu centros patst\u0101v\u012bgi. CQRS ir k\u013cuvis daudz vienk\u0101r\u0161\u0101ks, pateicoties bibliot\u0113ku, piem\u0113ram, RX, att\u012bst\u012bbai. Pirms 10 gadiem reti kur\u0161 t\u012bmek\u013ca vietne sp\u0113ja atbalst\u012bt t\u0101du. Event Sourcing ir ar\u012b neticami viegli konfigur\u0113ts, pateicoties jau gataviem konteineriem ar Apache Kafka. Pirms 10 gadiem tas b\u016btu bijis inov\u0101cija, tagad tas ir ikdieni\u0161\u0137s. L\u012bdz\u012bgi ar\u012b ar statisko satura mitin\u0101\u0161anu: pateicoties \u0113rt\u0101k\u0101m tehnolo\u0123ij\u0101m (t.sk. ar\u012b t\u0101p\u0113c, ka ir detaliz\u0113ta dokument\u0101cija un liela atbil\u017eu b\u0101ze), \u0161\u0101ds pieejas veids k\u013cuvis v\u0113l vienk\u0101r\u0161\u0101ks.<\/p>\n<p><\/p>\n<p>K\u0101 secin\u0101jums, ievie\u0161ana vair\u0101k\u0101m diezgan sare\u017e\u0123\u012bt\u0101m arhitekt\u016bras sh\u0113m\u0101m tagad ir k\u013cuvusi daudz vienk\u0101r\u0161\u0101ka, un t\u0101d\u0113\u013c to lab\u0101k apskat\u012bt iepriek\u0161. Ja desmit gadu vec\u0101 lietojumprogramm\u0101 atteic\u0101s no viena no iepriek\u0161 min\u0113tajiem risin\u0101jumiem augsto ievie\u0161anas un darb\u012bbas izmaksu d\u0113\u013c, tad tagad, jaunaj\u0101 lietojumprogramm\u0101 vai p\u0113c refaktoringa, var izveidot pakalpojumu, kas arhitekt\u016bras zi\u0146\u0101 b\u016bs gan papla\u0161in\u0101ms (veiktsp\u0113jas zi\u0146\u0101), gan gatavs jauniem klientu piepras\u012bjumiem (piem\u0113ram, personisko datu lokaliz\u0101cijai).<\/p>\n<p><\/p>\n<p>Un pats svar\u012bg\u0101kais: l\u016bdzu, neizmantojiet \u0161os pieejas veidus, ja jums ir vienk\u0101r\u0161a lietojumprogramma. J\u0101, t\u0101s ir gl\u012btas un interesantas, tom\u0113r vietnei ar maksim\u0101lo apmekl\u0113jumu 100 cilv\u0113ku bie\u017ei vien var pietikt ar klasisku monol\u012btu (vismaz no \u0101rpuses, iek\u0161pus\u0113 to var sadal\u012bt modulos utt.).<\/p>\n<p>Avots: <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.5 - 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\/lv\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.5\" \/>\n\t\t<meta property=\"og:locale\" content=\"lv_LV\" \/>\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\/lv\/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\udd47\u0112rti arhitekt\u016bras mode\u013ci | ProHoster","description":"Sveiki, Habr! \u0145emot v\u0113r\u0101 pa\u0161reiz\u0113j\u0101s koronav\u012brusa izrais\u012bt\u0101s situ\u0101cijas, da\u017ei interneta pakalpojumi ir s\u0101ku\u0161i sa\u0146emt palielin\u0101tu slodzi.","canonical_url":"https:\/\/prohoster.info\/lv\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"lv_LV","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\/lv\/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\/lv\/wp-json\/wp\/v2\/posts\/80035","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/comments?post=80035"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/posts\/80035\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/media\/80036"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/media?parent=80035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/categories?post=80035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/tags?post=80035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}