{"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\/da\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","title":{"rendered":"Praktiske arkitekturmodeller","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Hello, Habr!<\/p>\n<p><\/p>\n<p>I lyset af de nuv\u00e6rende omst\u00e6ndigheder p\u00e5 grund af coronaviruset har en r\u00e6kke internettjenester oplevet \u00f8get belastning. For eksempel <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\">har et af supermarkederne i Storbritannien simpelthen stoppet sin online bestillingstjeneste,<\/a><\/noindex>fordi kapaciteten ikke var tilstr\u00e6kkelig. Det er ikke altid muligt at hurtigere servere ved blot at tilf\u00f8je mere kraftfuldt udstyr, men kundeforesp\u00f8rgsler skal behandles (ellers vil de tage til konkurrenterne).<\/p>\n<p><\/p>\n<p>I denne artikel vil jeg kort gennemg\u00e5 popul\u00e6re praksisser, der kan skabe en hurtig og fejltolerant service. Jeg har dog kun udvalgt de udviklingsskemaer, som man i \u00f8jeblikket <strong>let kan bruge.<\/strong>For hvert punkt har du enten allerede eksisterende biblioteker eller muligheder for at l\u00f8se opgaven med en cloud-platform.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"gorizontalnoe-masshtabirovanie\">Horiskontalt skalerings<\/h1>\n<p><\/p>\n<p>Den mest enkle og velkendte tilgang. Betinget m\u00f8des der oftest to strategier for belastningsfordeling - horisontal og vertikal skalerings. <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\">I det f\u00f8rste tilf\u00e6lde<\/a><\/noindex> giver du tjenesterne mulighed for at arbejde parallelt, hvilket fordeler belastningen mellem dem. <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\">I det andet<\/a><\/noindex> bestiller du mere kraftfulde servere eller optimerer koden.<\/p>\n<p><\/p>\n<p>For eksempel vil jeg tage en abstrakt cloud-lagringstjeneste, som er en analog til OwnCloud, OneDrive og s\u00e5 videre.<\/p>\n<p><\/p>\n<p>Det standardbillede af et s\u00e5dant system er nedenfor, men det viser kun systemets kompleksitet. For vi skal finde en m\u00e5de at synkronisere tjenesterne p\u00e5. Hvad sker der, hvis en bruger gemmer en fil fra sin tablet, og derefter \u00f8nsker at se den p\u00e5 sin telefon?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturmodeller\" src=\"\/wp-content\/uploads\/2020\/05\/7512c6d8783f5e0a38cc0861b01e54c8.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nForskellen mellem metoderne: i vertikal skalerings er vi villige til at \u00f8ge kapaciteten af noderne, mens vi i horisontal skalering tilf\u00f8jer nye noder for at fordele belastningen.<\/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> er et ret vigtigt m\u00f8nster, da det g\u00f8r det muligt for forskellige klienter ikke kun at tilslutte sig forskellige tjenester, men ogs\u00e5 at modtage de samme str\u00f8mme af begivenheder. Dets fordele er ikke s\u00e5 \u00e5benlyse for en simpel applikation, men det er ekstremt vigtigt (og enkelt) for en overbelastet service. Dets essens er: indg\u00e5ende og udg\u00e5ende datastreams m\u00e5 ikke krydse hinanden. Det vil sige, du kan ikke sende en foresp\u00f8rgsel og forvente et svar, i stedet sender du en foresp\u00f8rgsel til tjeneste A, men modtager svaret i tjeneste B.<\/p>\n<p><\/p>\n<p>Den f\u00f8rste fordel ved denne tilgang er muligheden for at afbryde forbindelsen (i ordets brede forstand) under udf\u00f8relsen af en lang anmodning. Lad os tage en mere eller mindre standard sekvens som eksempel:<\/p>\n<p><\/p>\n<ol>\n<li>Klienten har sendt en anmodning til serveren.<\/li>\n<li>Serveren har startet en lang behandling.<\/li>\n<li>Serveren svarede klienten med resultatet.<\/li>\n<\/ol>\n<p><\/p>\n<p>Forestill dig, at der i punkt 2 opstod et forbindelsesbrud (eller netv\u00e6rket genoprettede forbindelsen, eller brugeren gik til en anden side og afbr\u00f8d forbindelsen). I dette tilf\u00e6lde vil det v\u00e6re sv\u00e6rt for serveren at sende et svar til brugeren med oplysninger om, hvad der blev behandlet. Ved at anvende CQRS vil sekvensen v\u00e6re lidt anderledes:<\/p>\n<p><\/p>\n<ol>\n<li>Klienten har tilmeldt sig opdateringer.<\/li>\n<li>Klienten har sendt en anmodning til serveren.<\/li>\n<li>Serveren svarede: \u00abAnmodning modtaget\u00bb.<\/li>\n<li>Serveren svarede med resultatet gennem kanalen fra punkt \u00ab1\u00bb.<\/li>\n<\/ol>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturmodeller\" src=\"\/wp-content\/uploads\/2020\/05\/8a00ea93eecc7cc0754122857c5f90d0.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Som det fremg\u00e5r, er skemaet lidt mere komplekst. Desuden er den intuitive anmodnings-svar tilgang frav\u00e6rende her. Men som det ses, vil et forbindelsesbrud under behandlingen af anmodningen ikke f\u00f8re til en fejl. Mere end det, hvis brugeren faktisk er tilsluttet tjenesten fra flere enheder (f.eks. fra en mobiltelefon og en tablet), kan man s\u00f8rge for, at svaret kommer til begge enheder.<\/p>\n<p><\/p>\n<p>Det interessante er, at koden til behandling af indkommende meddelelser bliver ensartet (ikke 100%) b\u00e5de for de begivenheder, som kunden selv har p\u00e5virket, samt for de \u00f8vrige begivenheder, herunder dem fra andre kunder.<\/p>\n<p><\/p>\n<p>Men i praksis f\u00e5r vi yderligere fordele, da den envejskommunikation kan behandles funktionelt (ved hj\u00e6lp af RX og lignende). Og dette er allerede en betydelig fordel, da applikationen i princippet kan g\u00f8res helt reaktiv, og endda anvende en funktionel tilgang. For st\u00f8rre programmer kan dette betydeligt spare ressourcer p\u00e5 udvikling og vedligeholdelse.<\/p>\n<p><\/p>\n<p>Hvis man kombinerer denne tilgang med horisontal skalering, f\u00e5r vi muligheden for at sende anmodninger til \u00e9n server, men modtage svar fra en anden. P\u00e5 den m\u00e5de kan klienten selv v\u00e6lge den tjeneste, der er mest praktisk for dem, og systemet kan stadig korrekt behandle begivenhederne internt.<\/p>\n<p><\/p>\n<h1 id=\"event-sourcing\">Event Sourcing<\/h1>\n<p><\/p>\n<p>Som du ved, er en af de centrale egenskaber ved et distribueret system frav\u00e6ret af en f\u00e6lles tid og en f\u00e6lles kritisk sektion. For en enkelt proces kan du lave synkronisering (p\u00e5 de samme mutexer), hvor du er sikker p\u00e5, at ingen andre udf\u00f8rer denne kode. Men for et distribueret system er det farligt, da det vil kr\u00e6ve overhead, og hele sk\u00f8nheden ved skalerbarhed vil g\u00e5 tabt \u2014 alle komponenter vil stadig vente p\u00e5 den samme.<\/p>\n<p><\/p>\n<p>Derfor f\u00e5r vi en vigtig konklusion \u2014 det er ikke muligt at synkronisere et hurtigt distribueret system, for da vil vi reducere ydeevnen. P\u00e5 den anden side har vi ofte brug for en vis konsistens mellem komponenterne. Og til dette kan vi anvende en tilgang med <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventuel konsistens<\/a><\/noindex>, hvor det garanteres, at i frav\u00e6r af data\u00e6ndringer over en vis periode efter den seneste opdatering (\"i sidste ende\") vil alle foresp\u00f8rgsler returnere den senest opdaterede v\u00e6rdi.<\/p>\n<p><\/p>\n<p>Det er vigtigt at forst\u00e5, at der ofte anvendes <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Consistency_model#Strict_consistency\">striks konsistens<\/a><\/noindex>, hvor hver node ejer den samme information (dette opn\u00e5s ofte, n\u00e5r en transaktion kun betragtes som bekr\u00e6ftet efter et svar fra den anden server). Der er dog nogle lempelser p\u00e5 grund af isolationsniveauer, men den overordnede id\u00e9 forbliver den samme \u2014 du kan leve i en helt konsistent verden.<\/p>\n<p><\/p>\n<p>Men lad os vende tilbage til det oprindelige problem. Hvis en del af systemet kan bygges med <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventuel konsistens<\/a><\/noindex>, kan vi bygge f\u00f8lgende skema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturmodeller\" src=\"\/wp-content\/uploads\/2020\/05\/33c80be6bc33bd897ca9b9e5525f9ae8.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vigtige egenskaber ved denne tilgang:<\/p>\n<p><\/p>\n<ul>\n<li>Hver indkommende foresp\u00f8rgsel placeres i en k\u00f8.<\/li>\n<li>Under behandlingen af en foresp\u00f8rgsel kan tjenesten ogs\u00e5 placere opgaver i andre k\u00f8er.<\/li>\n<li>Hver indkommende h\u00e6ndelse har et identifikationsnummer (der er n\u00f8dvendigt for deduplicering).<\/li>\n<li>K\u00f8en fungerer ideologisk efter \"append only\"-modellen. Elementer kan ikke fjernes eller omarrangeres fra den.<\/li>\n<li>K\u00f8en arbejder efter FIFO-princippet (undskyld for tautologien). Hvis der er behov for parallel eksekvering, skal objekterne flyttes til forskellige k\u00f8er i en af faserne.<\/li>\n<\/ul>\n<p><\/p>\n<p>Lad mig minde om, at vi ser p\u00e5 tilf\u00e6lde af online filopbevaring. I dette tilf\u00e6lde vil systemet se omtrent s\u00e5dan ud:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturmodeller\" src=\"\/wp-content\/uploads\/2020\/05\/b95efb29545dcde1db9432d12d00a1b1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Det er vigtigt at bem\u00e6rke, at tjenesterne p\u00e5 diagrammet ikke n\u00f8dvendigvis betyder en separat server. Selv processen kan v\u00e6re den samme. Det vigtigste er dog, at ideologisk er disse ting opdelt p\u00e5 en s\u00e5dan m\u00e5de, at det er nemt at anvende horisontal skalerbarhed.<\/p>\n<p><\/p>\n<p>Og for to brugere vil skemaet se s\u00e5dan ud (tjenester, der er designet til forskellige brugere, er angivet med forskellige farver):<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturmodeller\" src=\"\/wp-content\/uploads\/2020\/05\/4c4aadc8b9dd505c3ad743e69fee4fae.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Fordele ved en s\u00e5dan kombination:<\/p>\n<p><\/p>\n<ul>\n<li>Tjenesterne til behandling af information er opdelt. K\u00f8erne er ogs\u00e5 opdelt. Hvis vi skal \u00f8ge systemets kapacitet, skal vi blot starte flere tjenester p\u00e5 et st\u00f8rre antal servere.<\/li>\n<li>N\u00e5r vi modtager information fra brugeren, er vi ikke n\u00f8dvendigvis n\u00f8dt til at vente p\u00e5, at dataene er gemt fuldt ud. Tv\u00e6rtimod er det nok at svare \"ok\", og s\u00e5 kan vi gradvist begynde arbejdet. Desuden udglatter k\u00f8en spidserne, da tilf\u00f8jelsen af et nyt objekt sker hurtigt, og brugeren beh\u00f8ver ikke at vente p\u00e5 en fuld gennemgang af hele cyklussen.<\/li>\n<li>For eksempel har jeg tilf\u00f8jet en deduplikationstjeneste, der fors\u00f8ger at kombinere identiske filer. Hvis den k\u00f8rer l\u00e6nge i 1% af tilf\u00e6ldene, vil kunden stort set ikke bem\u00e6rke det (se ovenfor), hvilket er en stor fordel, da vi ikke l\u00e6ngere kr\u00e6ver hundrede procent hastighed og p\u00e5lidelighed.<\/li>\n<\/ul>\n<p><\/p>\n<p>Men der ses straks ogs\u00e5 ulemper:<\/p>\n<p><\/p>\n<ul>\n<li>Vores system har mistet streng konsistens. Det betyder, at hvis man f.eks. abonnerer p\u00e5 forskellige tjenester, s\u00e5 kan man teoretisk set f\u00e5 forskellige tilstande (da en af tjenesterne m\u00e5ske ikke n\u00e5r at modtage meddelelsen fra den interne k\u00f8). Som en anden konsekvens har systemet nu ikke nogen f\u00e6lles tid. Det vil sige, at man ikke kan sortere alle h\u00e6ndelser simpelthen efter modtagelsestidspunktet, da klokken mellem serverne muligvis ikke er synkroniseret (mere end det, s\u00e5 er det en utopi at have samme tid p\u00e5 to servere).<\/li>\n<li>Ingen h\u00e6ndelser kan nu simpelthen blive rullet tilbage (som man kunne g\u00f8re med en database). I stedet er det n\u00f8dvendigt at tilf\u00f8je en ny h\u00e6ndelse \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/49451237\/compensating-events-on-cqrs-es-architecture\">compensation event<\/a><\/noindex>, som vil \u00e6ndre den sidste tilstand til den \u00f8nskede. Som et eksempel fra et lignende omr\u00e5de: uden at overskrive historien (hvilket er skidt i mange tilf\u00e6lde) kan man i git ikke rulle et commit tilbage, men man kan lave et specielt <noindex><a rel=\"nofollow\" href=\"https:\/\/git-scm.com\/docs\/git-revert\">rollback commit<\/a><\/noindex>, som i bund og grund blot vil gendanne den gamle tilstand. Dog vil b\u00e5de den fejlagtige commit og rollback stadig v\u00e6re gemt i historikken.<\/li>\n<li>Dataskemaet kan \u00e6ndre sig fra version til version, men gamle h\u00e6ndelser kan nu ikke opdateres til den nye standard (da h\u00e6ndelser i princippet ikke kan \u00e6ndres).<\/li>\n<\/ul>\n<p><\/p>\n<p>Som det kan ses, passer Event Sourcing glimrende sammen med CQRS. Desuden er det generelt sv\u00e6rt at implementere et system med effektive og brugervenlige k\u00f8er uden at adskille datastreams, da der s\u00e5 skal tilf\u00f8jes synkroniseringspunkter, der vil neutralisere hele den positive effekt af k\u00f8erne. Ved at anvende begge tilgange samtidig skal programkode justeres en smule. I vores tilf\u00e6lde, n\u00e5r en fil sendes til serveren, modtages der kun en \u2018ok\u2019-besked som svar, hvilket blot betyder, at \u2018operationen med filtilf\u00f8jelsen er blevet gemt\u2019. Formelt set betyder dette ikke, at dataene allerede er tilg\u00e6ngelige p\u00e5 andre enheder (f.eks. kan deduplication service omstrukturere indekset). Men efter noget tid vil klienten modtage en meddelelse af typen \u2018fil X er gemt\u2019.<\/p>\n<p><\/p>\n<p>Resultatet bliver:<\/p>\n<p><\/p>\n<ul>\n<li>Antallet af statusser for filoverf\u00f8rsler stiger: i stedet for den klassiske \u2018fil sendt\u2019, f\u00e5r vi to: \u2018fil tilf\u00f8jet til serverens k\u00f8\u2019 og \u2018fil gemt i lageret\u2019. Sidstn\u00e6vnte betyder, at andre enheder allerede kan begynde at modtage filen (med forbehold for, at k\u00f8erne arbejder med forskellig hastighed).<\/li>\n<li>Da informationen om afsendelsen nu kommer via forskellige kanaler, er vi n\u00f8dt til at finde l\u00f8sninger for at modtage status for filbehandlingen. Som f\u00f8lge heraf, i mods\u00e6tning til det klassiske request-response, kan klienten genstartes under filbehandlingen, men status for denne behandling vil v\u00e6re korrekt. Og dette punkt fungerer i bund og grund out-of-the-box. Som resultat: vi er nu mere tolerante over for fejl.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sharding\">Sharding<\/h1>\n<p><\/p>\n<p>Som allerede beskrevet, har systemer med event sourcing ikke streng konsistens. Det betyder, at vi kan anvende flere lagre uden nogen form for synkronisering mellem dem. N\u00e5r vi n\u00e6rmer os vores opgave, kan vi:<\/p>\n<p><\/p>\n<ul>\n<li>Opdele filer efter typer. For eksempel kan billeder\/videoer dekodes og v\u00e6lges til en mere effektiv format.<\/li>\n<li>Adskil konti efter lande. P\u00e5 grund af mange love kan dette v\u00e6re n\u00f8dvendigt; men dette arkitekturdesign giver mulighed for automatisk at g\u00f8re det.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturmodeller\" src=\"\/wp-content\/uploads\/2020\/05\/dd310df700bc39c014d0105a3425fece.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvis du \u00f8nsker at overf\u00f8re data fra et lager til et andet, kan du ikke blot bruge de standardv\u00e6rkt\u00f8jer, der er tilg\u00e6ngelige. Desv\u00e6rre skal k\u00f8en stoppes, migrationen udf\u00f8res, og derefter genstartes den. Generelt kan data ikke overf\u00f8res 'on the fly', men hvis begivenhedsk\u00f8en er fuld og du har snapshots af de tidligere tilstande af lageret, kan vi genafspille begivenhederne p\u00e5 f\u00f8lgende m\u00e5de:<\/p>\n<p><\/p>\n<ul>\n<li>I Event Source har hver begivenhed sit eget id (ideelt set ikke-faldende). Det betyder, at vi kan tilf\u00f8je et felt i lageret - id'et for det sidst behandlede element.<\/li>\n<li>Vi duplikerer k\u00f8en, s\u00e5 alle begivenheder kan behandles for flere uafh\u00e6ngige lagre (det f\u00f8rste er det, hvor data allerede er gemt, og det andet er nyt, men endnu tomt). Den anden k\u00f8 behandles naturligvis endnu ikke.<\/li>\n<li>Vi starter den anden k\u00f8 (det vil sige, vi begynder at genafspille begivenheder).<\/li>\n<li>N\u00e5r den nye k\u00f8 er relativt tom (dvs. den gennemsnitlige tidsforskel mellem tilf\u00f8jelsen af et element og dets udtr\u00e6kning er acceptabel), kan vi begynde at skifte l\u00e6serne til det nye lager.<\/li>\n<\/ul>\n<p><\/p>\n<p>Som det fremg\u00e5r, har vi i systemet aldrig haft og har aldrig streng konsistens. Der eksisterer kun eventual consistency, hvilket giver en garanti for, at begivenheder behandles i den samme r\u00e6kkef\u00f8lge (dog muligvis med forskellige forsinkelser). Ved at udnytte dette kan vi relativt nemt overf\u00f8re data uden at stoppe systemet til den anden ende af kloden.<\/p>\n<p><\/p>\n<p>Dermed, forts\u00e6tter vi med vores eksempel p\u00e5 et online lagring for filer, giver denne arkitektur os allerede en r\u00e6kke fordele:<\/p>\n<p><\/p>\n<ul>\n<li>Vi kan flytte objekter t\u00e6ttere p\u00e5 brugerne, hvilket kan ske dynamisk. P\u00e5 den m\u00e5de kan kvaliteten af tjenesten \u00f8ges. <\/li>\n<li>Vi kan opbevare en del af dataene internt hos virksomhederne. For eksempel kr\u00e6ver Enterprise-brugere ofte, at deres data opbevares i kontrollerede datacentre (for at undg\u00e5 datal\u00e6k). Gennem sharding kan vi nemt underst\u00f8tte dette. Og opgaven bliver endnu lettere, hvis kunden har en kompatibel sky (for eksempel, <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>Og det vigtigste er, at vi ikke n\u00f8dvendigvis skal g\u00f8re det. For i starten ville det v\u00e6re tilstr\u00e6kkeligt med et enkelt lager til alle konti (s\u00e5 vi kan komme hurtigere i gang). Og n\u00f8glefunktionen ved dette system er, at det, selvom det er skalerbart, i udgangspunktet er ret simpelt. Man skal bare ikke straks skrive kode, der arbejder med en million separate uafh\u00e6ngige k\u00f8er osv. Hvis det bliver n\u00f8dvendigt, kan det g\u00f8res senere.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"static-content-hosting\">Statisk Indhold Hosting<\/h1>\n<p><\/p>\n<p>Dette punkt kan virke helt \u00e5benlyst, men det er stadig n\u00f8dvendigt for et mere eller mindre standard belastet applikation. Dets essens er enkel: al statisk indhold leveres ikke fra samme server, som applikationen er p\u00e5, men fra s\u00e6rlige, der er dedikeret til dette form\u00e5l. Som f\u00f8lge heraf udf\u00f8res disse operationer hurtigere (en typisk nginx leverer filer b\u00e5de hurtigere og billigere end en Java-server). Plus, CDN-arkitekturen (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Content_delivery_network\">Content Delivery Network<\/a><\/noindex>) g\u00f8r det muligt at placere vores filer t\u00e6ttere p\u00e5 slutbrugerne, hvilket positivt p\u00e5virker brugervenligheden af servicen.<\/p>\n<p><\/p>\n<p>Det simpleste og mest standard eksempel p\u00e5 statisk indhold er en samling af scripts og billeder til en hjemmeside. Det er ret enkelt \u2014 de er i forvejen kendte, hvorefter arkivet uploades til CDN-serverne, hvorfra det leveres til slutbrugerne.<\/p>\n<p><\/p>\n<p>Men i praksis kan en lignende tilgang anvendes for statisk indhold, som ligner lambda-arkitektur. Lad os g\u00e5 tilbage til vores opgave (online filopbevaring), hvor vi skal levere filer til brugerne. Den enkleste l\u00f8sning er at lave en service, der for hver brugerforesp\u00f8rgsel foretager alle n\u00f8dvendige kontroller (autorisation osv.), og derefter downloader filen direkte fra vores lager. Hovedproblemet ved denne tilgang er, at det statiske indhold (og en fil med en bestemt revision er i princippet statisk indhold) leveres af den samme server, der indeholder forretningslogikken. I stedet kan man lave f\u00f8lgende skema:<\/p>\n<p><\/p>\n<ul>\n<li>Serveren giver en URL til download. Den kan v\u00e6re i formatet file_id + key, hvor key er en mini-digitalskilt, der giver ret til adgang til ressourcen i de n\u00e6ste 24 timer.<\/li>\n<li>Udleveringen af filen h\u00e5ndteres af en simpel nginx med f\u00f8lgende indstillinger:\n<ul>\n<li>Cache af indhold. Da denne tjeneste kan befinde sig p\u00e5 en separat server, har vi givet os selv en fremtidig mulighed for at gemme alle de senest downloaded filer p\u00e5 disken.<\/li>\n<li>Kontrol af n\u00f8glen i forbindelse med oprettelsen af forbindelsen<\/li>\n<\/ul>\n<\/li>\n<li>Valgfrit: streaming af indhold. For eksempel, hvis vi komprimerer alle filer i tjenesten, kan vi udf\u00f8re udpakkningen direkte i denne modul. Som f\u00f8lge heraf: IO-operationer foretages, hvor de h\u00f8rer hjemme. En Java-arkiverer kan nemt allokere meget un\u00f8dig hukommelse, men at omskrive tjenesten med forretningslogik i betinget Rust\/C++ kan ogs\u00e5 vise sig at v\u00e6re ineffektivt. I vores tilf\u00e6lde anvendes der forskellige processer (eller endda tjenester), og derfor kan forretningslogik og IO-operationer opdeles ret effektivt.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturmodeller\" src=\"\/wp-content\/uploads\/2020\/05\/4dead07d5824938e09b986192ccc8f5e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Denne skema ligner ikke meget en distribution af statisk indhold (da vi ikke uploader hele pakken af statik et sted hen), men i realiteten besk\u00e6ftiger denne tilgang sig netop med distribution af uforanderlige data. Desuden kan dette skema generaliseres til andre tilf\u00e6lde, hvor indhold ikke blot er statisk, men kan pr\u00e6senteres som et s\u00e6t uforanderlige og utrad\u00e9rbare blokke (selvom de kan tilf\u00f8jes).<\/p>\n<p><\/p>\n<p>Som et andet eksempel (for at forst\u00e6rke det): hvis du har arbejdet med Jenkins\/TeamCity, ved du, at begge l\u00f8sninger er skrevet i Java. Begge repr\u00e6senterer en Java-proces, der h\u00e5ndterer b\u00e5de orkestrering af builds og indholdsstyring. Is\u00e6r har de begge opgaver som \"at overf\u00f8re en fil\/mappe fra serveren\". Eksempler inkluderer udlevering af artefakter, overf\u00f8rsel af kildekode (n\u00e5r agenten ikke downloader koden direkte fra arkivet, men serveren g\u00f8r det for den), adgang til logfiler. Alle disse opgaver varierer i IO-belastning. Det betyder, at serveren, der h\u00e5ndterer kompleks forretningslogik, ogs\u00e5 skal kunne effektivt skubbe store datam\u00e6ngder igennem. Og interessant nok kan en s\u00e5dan operation delegere til nginx p\u00e5 pr\u00e6cis samme m\u00e5de (bare husk at tilf\u00f8je datan\u00f8glen i foresp\u00f8rgslen).<\/p>\n<p><\/p>\n<p>Men hvis vi vender tilbage til vores system, f\u00e5r vi f\u00f8lgende skema:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturmodeller\" src=\"\/wp-content\/uploads\/2020\/05\/97cfbf5daaa6678a9eecc3169692f0fc.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Som det ses, er systemet blevet radikalt mere komplekst. Det er ikke l\u00e6ngere bare en mini-proces, der gemmer filer lokalt. Der kr\u00e6ves nu ikke bare simpel support, men ogs\u00e5 kontrol over API-versioner osv. Derfor, n\u00e5r alle diagrammer er tegnet, er det bedst at vurdere n\u00f8je, om omkostningerne til skalerbarhed er v\u00e6rd. Men hvis du \u00f8nsker at kunne skalere systemet (inklusive til at h\u00e5ndtere flere brugere), m\u00e5 du g\u00e5 p\u00e5 s\u00e5danne l\u00f8sninger. Til geng\u00e6ld er systemets arkitektur klar til at h\u00e5ndtere \u00f8get belastning (n\u00e6sten hver komponent kan klones til horisontal skalering). Systemet kan opdateres uden at stoppe det (bare nogle operationer vil midlertidigt blive lidt langsommere).<\/p>\n<p><\/p>\n<p>Som jeg allerede n\u00e6vnte i begyndelsen, oplever mange internet-tjenester nu en \u00f8get belastning. Og nogle af dem er faktisk begyndt at fungere d\u00e5rligt. I realiteten svigtede systemerne lige pr\u00e6cis, n\u00e5r virksomhederne skulle tjene penge. I stedet for at planl\u00e6gge leveringer i de kommende m\u00e5neder, sagde systemet simpelthen \"g\u00e5 til konkurrenterne\". Det er prisen for lav ydeevne: tabene opst\u00e5r netop n\u00e5r fortjenesten ville v\u00e6re h\u00f8jest.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Konklusion<\/h1>\n<p><\/p>\n<p>Alle disse tilgange var kendte tidligere. VK bruger allerede l\u00e6nge ideen om Static Content Hosting til udlevering af billeder. Mange online-spil bruger en Sharding-ordning til at opdele spillere efter regioner eller til at opdele spilomr\u00e5der (hvis verden er samlet). Event Sourcing metoden anvendes aktivt i e-mail. De fleste trader-apps, hvor data kontinuerligt kommer ind, er faktisk bygget p\u00e5 CQRS-metoden for at kunne filtrere de indkomne data. Og horisontal skalering er blevet anvendt i mange tjenester i et stykke tid.<\/p>\n<p><\/p>\n<p>Men det vigtigste er, at alle disse m\u00f8nstre nu er meget lettere at anvende i moderne applikationer (hvis de er relevante, selvf\u00f8lgelig). Cloud-l\u00f8sninger tilbyder sharding og horisontal skalerbarhed med det samme, hvilket er meget lettere end selv at bestille forskellige dedikerede servere i forskellige datacentre. CQRS er blevet meget lettere, ikke mindst p\u00e5 grund af udviklingen af biblioteker som RX. For ti \u00e5r siden ville sj\u00e6ldne websteder kunne underst\u00f8tte noget s\u00e5dant. Event sourcing konfigureres ogs\u00e5 utrolig nemt takket v\u00e6re f\u00e6rdige containere med Apache Kafka. For ti \u00e5r siden ville det have v\u00e6ret en innovation; nu er det almindelighed. Tilsvarende med statisk indhold hosting: p\u00e5 grund af mere brugervenlige teknologier (herunder detaljeret dokumentation og et stort sp\u00f8rgeskema) er denne tilgang blevet endnu enklere.<\/p>\n<p><\/p>\n<p>Som resultat er implementeringen af en r\u00e6kke ret komplekse arkitekturm\u00f8nstre nu blevet meget lettere, og derfor er det bedst at kigge n\u00e6rmere p\u00e5 dem p\u00e5 forh\u00e5nd. Hvis et ti-\u00e5rigt program har forkastet en af l\u00f8sningerne ovenfor p\u00e5 grund af de h\u00f8je omkostninger ved implementering og drift, kan man nu i en ny applikation eller efter refaktorering skabe en service, som arkitektonisk allerede vil v\u00e6re b\u00e5de skalerbar (i forhold til ydeevne) og klar til nye anmodninger fra kunderne (for eksempel til lokalisering af persondata).<\/p>\n<p><\/p>\n<p>Og det vigtigste: brug venligst ikke disse tilgange, hvis du har en simpel applikation. Ja, de er smukke og interessante, men for en hjemmeside med et spidsbelastning p\u00e5 100 bes\u00f8gende, kan man ofte klare sig med en klassisk monolit (i det mindste udefra; indeni kan alt opdeles i moduler osv.).<\/p>\n<p>Kilde: <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\/da\/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=\"da_DK\" \/>\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\/da\/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\udd47Praktiske arkitekturm\u00f8nstre | ProHoster","description":"Hej, Habr! I lyset af de nuv\u00e6rende omst\u00e6ndigheder p\u00e5 grund af coronavirus er en r\u00e6kke internet-tjenester begyndt at opleve \u00f8get belastning.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/80035","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=80035"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/80035\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/80036"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=80035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=80035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=80035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}