{"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\/no\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","title":{"rendered":"Praktiske arkitekturm\u00f8nstre","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Hei, Habr!<\/p>\n<p><\/p>\n<p>I lys av de n\u00e5v\u00e6rende hendelsene p\u00e5 grunn av coronaviruset har flere internetttjenester begynt \u00e5 oppleve \u00f8kt 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\">en av detaljhandelskjeden i Storbritannia stoppet bare nettsiden for online bestillinger,<\/a><\/noindex>, fordi de ikke hadde nok kapasitet. Og det er langt fra alltid mulig \u00e5 \u00f8ke serverens ytelse bare ved \u00e5 legge til kraftigere utstyr, men foresp\u00f8rslene fra kundene m\u00e5 h\u00e5ndteres (eller s\u00e5 g\u00e5r de til konkurrentene).<\/p>\n<p><\/p>\n<p>I denne artikkelen vil jeg kort fortelle om popul\u00e6re praksiser som kan gj\u00f8re tjenesten rask og robust. Men av de mulige utviklingsskjemaene har jeg bare valgt de som n\u00e5 <strong>er lette \u00e5 bruke.<\/strong>For hvert punkt har du enten eksisterende biblioteker eller muligheten til \u00e5 l\u00f8se oppgaven ved hjelp av en skyplattform.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"gorizontalnoe-masshtabirovanie\">Horiskontal skalering<\/h1>\n<p><\/p>\n<p>Det enkleste og mest kjente punktet. Man kan grovt sett si at de to mest brukte lastbalanseringsskjemaene er horiskontal og vertikal skalering. <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 tilfellet<\/a><\/noindex> lar du tjenestene jobbe samtidig, og dermed fordeler du belastningen mellom 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 andre<\/a><\/noindex> bestiller du kraftigere servere eller optimaliserer koden.<\/p>\n<p><\/p>\n<p>Som eksempel tar jeg en abstrakt skyfilerlagring, det vil si en slags analog av OwnCloud, OneDrive osv.<\/p>\n<p><\/p>\n<p>Standardbildet av et slikt skjema er nedenfor, men det viser bare kompleksiteten i systemet. For vi m\u00e5 p\u00e5 en eller annen m\u00e5te synkronisere tjenestene. Hva skjer hvis brukeren lagret en fil fra nettbrettet og deretter \u00f8nsker \u00e5 se den fra telefonen?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturm\u00f8nstre\" src=\"\/wp-content\/uploads\/2020\/05\/7512c6d8783f5e0a38cc0861b01e54c8.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nForskjellen mellom tiln\u00e6rmingene: i vertikal skalering er vi klare til \u00e5 \u00f8ke kraften i nodene, mens i horiskontal skalering legger vi til nye noder for \u00e5 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 ganske viktig m\u00f8nster, siden det lar forskjellige kunder ikke bare koble til forskjellige tjenester, men ogs\u00e5 motta lignende hendelsesstr\u00f8mmer. Dets fordeler er ikke s\u00e5 \u00e5penbare for en enkel applikasjon, men det er ekstremt viktig (og enkelt) for en tung belastes tjeneste. Dets essens: innkommende og utg\u00e5ende datastreamer skal ikke krysse hverandre. Det vil si at du ikke kan sende en foresp\u00f8rsel og forvente et svar, i stedet sender du en foresp\u00f8rsel til tjeneste A, men f\u00e5r svar i tjeneste B.<\/p>\n<p><\/p>\n<p>Den f\u00f8rste fordelen med denne tiln\u00e6rmingen er muligheten til \u00e5 bryte forbindelsen (i vid forstand av ordet) under behandling av en lang foresp\u00f8rsel. La oss ta et mer eller mindre standard forl\u00f8p som eksempel:<\/p>\n<p><\/p>\n<ol>\n<li>Klienten sendte en foresp\u00f8rsel til serveren.<\/li>\n<li>Serveren startet en lang behandling.<\/li>\n<li>Serveren svarte klienten med resultatet.<\/li>\n<\/ol>\n<p><\/p>\n<p>La oss anta at det skjedde en avbrudd i forbindelsen i punkt 2 (enten nettverket koblet fra igjen, eller brukeren gikk til en annen side og br\u00f8t forbindelsen). I s\u00e5 fall vil det bli vanskelig for serveren \u00e5 sende svaret til brukeren med informasjonen om hva som ble behandlet. Ved \u00e5 bruke CQRS vil forl\u00f8pet v\u00e6re litt annerledes:<\/p>\n<p><\/p>\n<ol>\n<li>Klienten abonnerte p\u00e5 oppdateringer.<\/li>\n<li>Klienten sendte en foresp\u00f8rsel til serveren.<\/li>\n<li>Serveren svarte 'foresp\u00f8rsel mottatt'.<\/li>\n<li>Serveren svarte med resultatet gjennom kanalen fra punkt '1'.<\/li>\n<\/ol>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturm\u00f8nstre\" src=\"\/wp-content\/uploads\/2020\/05\/8a00ea93eecc7cc0754122857c5f90d0.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Som vi kan se, er oppsettet litt mer komplisert. Videre er den intuitive request-response-tiln\u00e6rmingen frav\u00e6rende her. Men som vi kan se, vil et avbrudd i forbindelsen under behandlingen av foresp\u00f8rselen ikke f\u00f8re til en feil. Dessuten, hvis brukeren faktisk er koblet til tjenesten fra flere enheter (for eksempel fra mobiltelefon og nettbrett), kan vi s\u00f8rge for at svaret kommer til begge enheter.<\/p>\n<p><\/p>\n<p>Det interessante er at koden for h\u00e5ndtering av innkommende meldinger blir lik (ikke 100%) for b\u00e5de hendelser p\u00e5virket av klienten selv og for andre hendelser, inkludert fra andre kunder.<\/p>\n<p><\/p>\n<p>Imidlertid f\u00e5r vi i praksis ytterligere fordeler ved at den \u00e9nveis str\u00f8mmen kan behandles p\u00e5 funksjonell m\u00e5te (ved hjelp av RX og lignende). Og dette er allerede en stor fordel, for i prinsippet kan applikasjonen gj\u00f8res helt reaktiv, samtidig som man bruker en funksjonell tiln\u00e6rming. For store programmer kan dette betydelig spare ressurser til utvikling og vedlikehold.<\/p>\n<p><\/p>\n<p>Hvis vi kombinerer denne tiln\u00e6rmingen med horisontal skalering, f\u00e5r vi muligheten til \u00e5 sende foresp\u00f8rslene til \u00e9n server, men motta svar fra en annen. Dermed kan klienten selv velge den tjenesten som passer ham best, mens systemet internt fortsatt vil kunne h\u00e5ndtere hendelsene korrekt.<\/p>\n<p><\/p>\n<h1 id=\"event-sourcing\">Event Sourcing<\/h1>\n<p><\/p>\n<p>Som du vet, er en av hovedtrekkene ved et distribuert system frav\u00e6ret av felles tid og felles kritisk seksjon. For \u00e9n prosess kan du oppn\u00e5 synkronisering (med de samme mutexene), hvor du er trygg p\u00e5 at ingen andre utf\u00f8rer denne koden. Men for et distribuert system er dette risikabelt, da det vil kreve overhead, og alt det fantastiske med skalering blir \u00f8delagt \u2013 alle komponenter m\u00e5 vente p\u00e5 \u00e9n.<\/p>\n<p><\/p>\n<p>Her f\u00e5r vi en viktig faktum \u2013 en rask distribuert system kan ikke synkroniseres, for da vil vi redusere ytelsen. P\u00e5 den annen side er det ofte n\u00f8dvendig med en bestemt konsistens av komponentene. Og for dette kan vi bruke tiln\u00e6rmingen med <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventuell konsistens<\/a><\/noindex>, hvor det garanteres at, dersom det ikke skjer noen datamessige endringer over en viss periode etter den siste oppdateringen (\u00abtil slutt\u00bb), vil alle foresp\u00f8rslene returnere den siste oppdaterte verdien.<\/p>\n<p><\/p>\n<p>Det er viktig \u00e5 forst\u00e5 at for klassiske databaser, benyttes ofte <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Consistency_model#Strict_consistency\">streng konsistens<\/a><\/noindex>, hvor hver node har identisk informasjon (dette oppn\u00e5s ofte n\u00e5r en transaksjon anses \u00e5 v\u00e6re etablert f\u00f8rst etter svar fra den andre serveren). Her finnes det noen lettelser p\u00e5 grunn av isolasjonsniv\u00e5er, men den generelle essensen forblir den samme \u2013 du kan leve i en helt konsistent verden.<\/p>\n<p><\/p>\n<p>Men la oss g\u00e5 tilbake til den opprinnelige oppgaven. Hvis en del av systemet kan bygges med <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Eventual_consistency\">eventuell konsistens<\/a><\/noindex>, kan vi konstruere f\u00f8lgende skjema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturm\u00f8nstre\" src=\"\/wp-content\/uploads\/2020\/05\/33c80be6bc33bd897ca9b9e5525f9ae8.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Viktige trekk ved denne tiln\u00e6rmingen:<\/p>\n<p><\/p>\n<ul>\n<li>Hver innkommende foresp\u00f8rsel plasseres i en enkelt k\u00f8.<\/li>\n<li>Under behandlingen av foresp\u00f8rselen kan tjenesten ogs\u00e5 plassere oppgaver i andre k\u00f8er.<\/li>\n<li>Hver innkommende hendelse har en identifikator (som er n\u00f8dvendig for deduplisering).<\/li>\n<li>K\u00f8en fungerer ideologisk etter \u00abappend only\u00bb-prinsippet. Det er ikke mulig \u00e5 slette elementer eller omorganisere dem.<\/li>\n<li>K\u00f8en fungerer etter FIFO-prinsippet (unnskyld for tautologien). Hvis vi trenger parallell behandling, b\u00f8r objektene overf\u00f8res til forskjellige k\u00f8er i ett av trinnene.<\/li>\n<\/ul>\n<p><\/p>\n<p>Husk at vi ser p\u00e5 tilfelle av en online filserver. I dette tilfelle vil systemet se omtrent slik ut:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturm\u00f8nstre\" src=\"\/wp-content\/uploads\/2020\/05\/b95efb29545dcde1db9432d12d00a1b1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Det er viktig at tjenestene i diagrammet ikke n\u00f8dvendigvis betyr en egen server. Selv prosessen kan v\u00e6re den samme. Det viktigste er imidlertid at disse tingene er ideologisk delt opp p\u00e5 en m\u00e5te som gj\u00f8r det enkelt \u00e5 bruke horisontal skalering.<\/p>\n<p><\/p>\n<p>Og for to brukere vil skjemaet se slik ut (tjenester beregnet for forskjellige brukere er merket med forskjellige farger):<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturm\u00f8nstre\" src=\"\/wp-content\/uploads\/2020\/05\/4c4aadc8b9dd505c3ad743e69fee4fae.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Fordeler med en slik kombinasjon:<\/p>\n<p><\/p>\n<ul>\n<li>Informasjonsklargj\u00f8ringstjenester er delt. Kj\u00f8ene er ogs\u00e5 delt. Hvis vi trenger \u00e5 \u00f8ke systemets kapasitet, m\u00e5 vi bare kj\u00f8re flere tjenester p\u00e5 et st\u00f8rre antall servere.<\/li>\n<li>N\u00e5r vi mottar informasjon fra brukeren, er det ikke n\u00f8dvendig \u00e5 vente p\u00e5 at dataene er fullstendig lagret. Tvert imot, vi trenger bare \u00e5 svare \"ok\", og deretter kan vi gradvis begynne arbeidet. I tillegg jevner k\u00f8en ut topper, da tillegg av nye objekter skjer raskt, og brukeren trenger ikke \u00e5 vente p\u00e5 en full gjennomgang av hele syklusen.<\/li>\n<li>Som et eksempel har jeg lagt til en deduplication-tjeneste, som pr\u00f8ver \u00e5 sl\u00e5 sammen identiske filer. Hvis den jobber lenge i 1 % av tilfellene, vil kunden nesten ikke merke det (se over), noe som er en stor fordel, ettersom vi ikke lenger krever hundre prosent hastighet og p\u00e5litelighet.<\/li>\n<\/ul>\n<p><\/p>\n<p>Men ulempene er ogs\u00e5 umiddelbart \u00e5penbare:<\/p>\n<p><\/p>\n<ul>\n<li>Systemet v\u00e5rt har mistet streng samsvar. Dette betyr at hvis man for eksempel abonnerer p\u00e5 forskjellige tjenester, kan man teoretisk f\u00e5 forskjellige tilstander (da en av tjenestene kan hende \u00e5 ikke motta varslingen fra den interne k\u00f8en i tide). Som et annet konsekvens, har systemet n\u00e5 ikke noe felles tidspunkt. Det vil si at man for eksempel ikke kan sortere alle hendelser bare etter tidspunktet for ankomst, da klokken mellom serverne ikke n\u00f8dvendigvis er synkronisert (mer enn det, lik tid p\u00e5 to servere er en utopi).<\/li>\n<li>Ingen hendelser kan n\u00e5 enkelt rulles tilbake (som man ville kunne gjort med en database). I stedet m\u00e5 man legge til en ny hendelse \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/49451237\/compensating-events-on-cqrs-es-architecture\">compensation event<\/a><\/noindex>, som vil endre den siste tilstanden til den n\u00f8dvendige. Som et eksempel fra et lignende felt: uten \u00e5 overskrive historien (som er d\u00e5rlig i en rekke tilfeller) i git kan man ikke rulle tilbake et commit, men man kan lage et spesial <noindex><a rel=\"nofollow\" href=\"https:\/\/git-scm.com\/docs\/git-revert\">rollback commit<\/a><\/noindex>, som i hovedsak bare vil returnere den gamle tilstanden. Men b\u00e5de den feilaktige commit og rollback vil forbli i historien.<\/li>\n<li>Dataskjemaet kan endres fra utgivelse til utgivelse, men gamle hendelser kan n\u00e5 ikke oppdateres til den nye standarden (siden hendelser generelt ikke kan endres).<\/li>\n<\/ul>\n<p><\/p>\n<p>Som vi ser, fungerer Event Sourcing utmerket med CQRS. Dessuten er det allerede vanskelig \u00e5 implementere et system med effektive og brukervennlige k\u00f8er uten \u00e5 skille datastreamer, ettersom vi m\u00e5 legge til synkroniseringspunkter som vil n\u00f8ytralisere hele den positive effekten av k\u00f8ene. N\u00e5r begge tiln\u00e6rmingene brukes samtidig, m\u00e5 koden for programmet justeres litt. I v\u00e5rt tilfelle, n\u00e5r en fil sendes til serveren, kommer svaret tilbake som bare \"ok\", som bare betyr at \"operasjonen med \u00e5 legge til filen er lagret\". Formelt betyr dette ikke at dataene allerede er tilgjengelige p\u00e5 andre enheter (for eksempel kan dedupliseringssystemet omstrukturere indeksen). Men etter en tid vil klienten motta et varsel i form av \"fil X er lagret\".<\/p>\n<p><\/p>\n<p>Som resultat:<\/p>\n<p><\/p>\n<ul>\n<li>Antallet statuser for filsending \u00f8ker: i stedet for den klassiske \"fil sendt\" f\u00e5r vi to: \"fil lagt til i k\u00f8 p\u00e5 serveren\" og \"fil lagret i lagring\". Det siste betyr at andre enheter allerede kan begynne \u00e5 motta filen (med forbehold om at k\u00f8ene jobber med ulik hastighet).<\/li>\n<li>P\u00e5 grunn av at informasjon om sending n\u00e5 kommer over forskjellige kanaler, m\u00e5 vi finne l\u00f8sninger for \u00e5 motta status for filbehandling. Som f\u00f8lge av dette: i motsetning til klassisk request-response, kan klienten startes p\u00e5 nytt mens filen behandles, men statusen for denne behandlingen vil fortsatt v\u00e6re korrekt. Og dette punktet fungerer stort sett ut av boksen. Som konsekvens er vi n\u00e5 mer tolerante overfor feil.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"sharding\">Sharding<\/h1>\n<p><\/p>\n<p>Som allerede beskrevet tidligere, mangler systemer med event sourcing streng konsistens. Dette betyr at vi kan bruke flere lagringsl\u00f8sninger uten noen synkronisering mellom dem. N\u00e6rmere v\u00e5r oppgave kan vi:<\/p>\n<p><\/p>\n<ul>\n<li>Dele filer etter typer. For eksempel kan bilder\/videoer dekodes og velge en mer effektivt format.<\/li>\n<li>Skille kontoene etter land. P\u00e5 grunn av mange lover kan dette v\u00e6re n\u00f8dvendig, men denne arkitekturmodellen gir den muligheten automatisk.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturm\u00f8nstre\" src=\"\/wp-content\/uploads\/2020\/05\/dd310df700bc39c014d0105a3425fece.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvis du vil flytte data fra ett lagringssted til et annet, kan standardmetoder ikke brukes. Dessverre m\u00e5 k\u00f8en stoppes, migreringen gj\u00f8res, og deretter startes den igjen. Generelt kan data ikke flyttes \u00abi sanntid\u00bb, men dersom alle hendelsesk\u00f8ene lagres fullstendig, og du har kopier av tidligere tilstander av lagringsstedet, kan vi gjengi hendelsene p\u00e5 f\u00f8lgende m\u00e5te:<\/p>\n<p><\/p>\n<ul>\n<li>I Event Source har hver hendelse sin egen identifikator (ideelt sett \u2014 ikke avtagende). Det betyr at vi kan legge til et felt i lagringsstedet \u2014 id for det siste behandlede elementet.<\/li>\n<li>Vi dupliserer k\u00f8en, slik at alle hendelsene kan behandles for flere uavhengige lagringssteder (den f\u00f8rste er det som allerede har dataene, og den andre er ny, men enn\u00e5 tom). Den andre k\u00f8en behandles selvf\u00f8lgelig ikke enn\u00e5.<\/li>\n<li>Vi starter den andre k\u00f8en (alts\u00e5 begynner vi \u00e5 gjengi hendelsene).<\/li>\n<li>N\u00e5r den nye k\u00f8en er relativt tom (det vil si at den gjennomsnittlige tiden mellom \u00e5 legge til et element og \u00e5 hente det igjen er akseptabel), kan vi begynne \u00e5 bytte leserne til det nye lagringsstedet.<\/li>\n<\/ul>\n<p><\/p>\n<p>Som det fremg\u00e5r, har vi i systemet v\u00e5rt aldri hatt og har fortsatt ikke strenge konsistenser. Det finnes bare eventual consistency, som betyr at det er garantert at hendelsene behandles i samme rekkef\u00f8lge (men kanskje med ulik forsinkelse). Ved \u00e5 dra nytte av dette kan vi relativt enkelt flytte data uten \u00e5 stoppe systemet til den andre siden av kloden.<\/p>\n<p><\/p>\n<p>Dermed, ved \u00e5 fortsette med v\u00e5rt eksempel om et online lagringssted for filer, gir denne arkitekturen oss allerede flere fordeler:<\/p>\n<p><\/p>\n<ul>\n<li>Vi kan flytte objektene n\u00e6rmere brukerne, p\u00e5 en dynamisk m\u00e5te. Dette kan forbedre kvaliteten p\u00e5 tjenesten. <\/li>\n<li>Vi kan lagre deler av dataene internt i selskapene. For eksempel krever Enterprise-brukere ofte at deres data lagres i kontrollerte datasentre (for \u00e5 unng\u00e5 datalekkasjer). Gjennom sharding kan vi enkelt st\u00f8tte dette. Og oppgaven blir enda enklere 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>Det viktigaste \u00e4r att vi kanske inte beh\u00f6ver g\u00f6ra det. F\u00f6rst och fr\u00e4mst skulle vi vara n\u00f6jda med en enda lagring f\u00f6r alla konton (f\u00f6r att snabbare kunna b\u00f6rja arbeta). Nyckelfunktionen i detta system \u00e4r att, \u00e4ven om det \u00e4r skalbart, \u00e4r det relativt enkelt i b\u00f6rjan. Man beh\u00f6ver bara inte skriva kod som fungerar med en m\u00e4ngd separata oberoende k\u00f6er osv. Om det beh\u00f6vs kan det g\u00f6ras i framtiden.<\/li>\n<\/ul>\n<p><\/p>\n<h1 id=\"static-content-hosting\">Statisk Inneh\u00e5lls Hosting<\/h1>\n<p><\/p>\n<p>Denna punkt kan verka helt uppenbar, men den \u00e4r \u00e4nd\u00e5 n\u00f6dv\u00e4ndig f\u00f6r en mer eller mindre standardbelastad applikation. Dess k\u00e4rna \u00e4r enkel: all statisk inneh\u00e5ll distribueras inte fr\u00e5n samma server som applikationen, utan fr\u00e5n speciella servrar som \u00e4r avsedda f\u00f6r detta \u00e4ndam\u00e5l. Som en f\u00f6ljd av detta utf\u00f6rs dessa operationer snabbare (hypotetisk nginx levererar filer b\u00e5de snabbare och mer kostnadseffektivt \u00e4n en Java-server). Dessutom g\u00f6r CDN-arkitekturen (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Content_delivery_network\">Inneh\u00e5llsleveransn\u00e4tverk<\/a><\/noindex>) att vi kan placera v\u00e5ra filer n\u00e4rmare slutanv\u00e4ndarna, vilket positivt p\u00e5verkar anv\u00e4ndarv\u00e4nligheten.<\/p>\n<p><\/p>\n<p>Det enklaste och mest standardiserade exemplet p\u00e5 statiskt inneh\u00e5ll \u00e4r en upps\u00e4ttning skript och bilder f\u00f6r en webbplats. Med dem \u00e4r allt enkelt \u2013 de \u00e4r k\u00e4nda i f\u00f6rv\u00e4g, d\u00e4refter laddas arkivet upp p\u00e5 CDN-servrarna, fr\u00e5n vilka det distribueras till slutanv\u00e4ndarna.<\/p>\n<p><\/p>\n<p>Men i praktiken kan ett liknande tillv\u00e4gag\u00e5ngss\u00e4tt anv\u00e4ndas f\u00f6r statiskt inneh\u00e5ll som liknar lambda-arkitektur. L\u00e5t oss \u00e5terv\u00e4nda till v\u00e5r uppgift (ett online lagringsutrymme f\u00f6r filer), d\u00e4r vi beh\u00f6ver dela filer med anv\u00e4ndarna. Den enklaste l\u00f6sningen \u00e4r att skapa en tj\u00e4nst som f\u00f6r varje anv\u00e4ndarf\u00f6rfr\u00e5gan g\u00f6r alla n\u00f6dv\u00e4ndiga kontroller (beh\u00f6righet osv.), och sedan laddar ner filen direkt fr\u00e5n v\u00e5rt lagringsutrymme. Huvudnackdelen med detta tillv\u00e4gag\u00e5ngss\u00e4tt \u00e4r att det statiska inneh\u00e5llet (och en fil med en viss revision \u00e4r i princip statiskt inneh\u00e5ll) distribueras av samma server som inneh\u00e5ller aff\u00e4rslogiken. Ist\u00e4llet kan man skapa f\u00f6ljande schema:<\/p>\n<p><\/p>\n<ul>\n<li>Servern tillhandah\u00e5ller en URL f\u00f6r nedladdning. Den kan ha formatet file_id + key, d\u00e4r key \u00e4r en mini-nummersignatur som ger r\u00e4tt till \u00e5tkomst till resursen under de kommande 24 timmarna.<\/li>\n<li>Nedladdningen av filen hanteras av en enkel nginx med f\u00f6ljande alternativ:\n<ul>\n<li>Caching of content. Since this service can be located on a separate server, we have allowed for the future possibility of storing all recently downloaded files on disk.<\/li>\n<li>Key check at the moment of connection creation<\/li>\n<\/ul>\n<\/li>\n<li>Optionally: streaming content processing. For example, if we compress all files in the service, we can perform the unzipping directly in this module. As a result, IO operations are performed where they should be. A Java archiver may allocate a lot of extra memory, but rewriting the service with business logic in conditional Rust\/C++ may also prove ineffective. In our case, we use different processes (or even services), allowing for a fairly effective separation of business logic and IO operations.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturm\u00f8nstre\" src=\"\/wp-content\/uploads\/2020\/05\/4dead07d5824938e09b986192ccc8f5e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>This scheme does not closely resemble serving static content (since we are not unloading the entire static package somewhere), but in reality, this approach is precisely what deals with serving immutable data. Moreover, this scheme can be generalized to other cases where the content is not just static but can be represented as a set of immutable and non-deletable blocks (although they can be added).<\/p>\n<p><\/p>\n<p>Et annet eksempel (for \u00e5 understreke): Hvis du har jobbet med Jenkins\/TeamCity, vet du at begge l\u00f8sningene er skrevet i Java. Begge representerer en Java-prosess som h\u00e5ndterer b\u00e5de orkestrering av bygg og innholdsh\u00e5ndtering. Spesifikt har de begge oppgaver som g\u00e5r ut p\u00e5 \u00e5 \u00aboverf\u00f8re fil\/mapp fra server\u00bb. For eksempel: utgivelse av artefakter, overf\u00f8ring av kildekode (n\u00e5r agenten ikke laster ned koden direkte fra depotet, men dette gj\u00f8res av serveren), tilgang til logger. Alle disse oppgavene har forskjellig IO-belastning. Det vil si at serveren, som er ansvarlig for kompleks forretningslogikk, ogs\u00e5 m\u00e5 kunne effektivt h\u00e5ndtere store datamengder. Og det mest interessante er at en slik operasjon kan delegeres til nginx p\u00e5 n\u00f8yaktig samme m\u00e5te (bare at foresp\u00f8rselen m\u00e5 inkludere en datan\u00f8kkel).<\/p>\n<p><\/p>\n<p>However, if we return to our system, the resulting scheme is as follows:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Praktiske arkitekturm\u00f8nstre\" src=\"\/wp-content\/uploads\/2020\/05\/97cfbf5daaa6678a9eecc3169692f0fc.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Som synlig, har systemet blitt radikalt mer komplisert. N\u00e5 er det ikke bare en liten prosess som lagrer filer lokalt. N\u00e5 kreves det ikke akkurat den enkleste st\u00f8tten, kontroll av API-versjoner, osv. Derfor, etter at alle diagrammer er tegnet, er det best \u00e5 vurdere i detalj om utvidelsen av slike kostnader er verdt det. Men hvis du \u00f8nsker \u00e5 kunne utvide systemet (inkludert for \u00e5 h\u00e5ndtere et st\u00f8rre antall brukere), m\u00e5 du g\u00e5 for slike l\u00f8sninger. Som et resultat, er systemarkitekturen klar for \u00f8kt belastning (nesten hver komponent kan klones for horisontal skalering). Systemet kan oppdateres uten \u00e5 stoppe det (bare noen operasjoner vil bli litt forsinket).<\/p>\n<p><\/p>\n<p>Som jeg allerede nevnte i starten, har en rekke internettjenester n\u00e5 begynt \u00e5 oppleve \u00f8kt belastning. Og noen av dem har bare sluttet \u00e5 fungere skikkelig. Faktisk feilet systemene nettopp i det \u00f8yeblikket bedriften skulle tjene penger. I stedet for utsatt levering, i stedet for \u00e5 tilby kundene \u2018planlegg leveringen for de kommende m\u00e5nedene\u2019, sa systemet bare \u2018g\u00e5 til konkurrentene\u2019. Dette er prisen p\u00e5 lav ytelse: tapene skjer nettopp n\u00e5r inntektene ville v\u00e6rt h\u00f8yest.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Konklusjon<\/h1>\n<p><\/p>\n<p>Alle disse tiln\u00e6rmingene har v\u00e6rt kjent f\u00f8r. Det samme VK har lenge brukt ideen om Static Content Hosting for \u00e5 levere bilder. Mange nettspill bruker Sharding-mekanismen for \u00e5 dele spillere etter regioner eller for \u00e5 dele spillomr\u00e5der (hvis selve verden er enhetlig). Event Sourcing-tiln\u00e6rmingen er aktivt brukt i e-post. De fleste applikasjoner for tradere, hvor data kontinuerlig kommer inn, er faktisk bygget p\u00e5 CQRS-tiln\u00e6rmingen for \u00e5 kunne filtrere de mottatte dataene. Og horisontal skalering har blitt brukt i mange tjenester en god stund.<\/p>\n<p><\/p>\n<p>Men det viktigste er at alle disse m\u00f8nstrene har blitt veldig enkle \u00e5 bruke i moderne applikasjoner (forutsatt at de er relevante, selvf\u00f8lgelig). Skyene tilbyr Sharding og horisontal skalering umiddelbart, noe som er mye lettere enn \u00e5 bestille forskjellige dedikerte servere i ulike datasentre p\u00e5 egenh\u00e5nd. CQRS er mye enklere n\u00e5, delvis p\u00e5 grunn av utviklingen av biblioteker som RX. For ti \u00e5r siden ville det v\u00e6rt sjeldent for et nettsted \u00e5 st\u00f8tte noe slikt. Event Sourcing konfigureres ogs\u00e5 utrolig enkelt takket v\u00e6re allerede tilgjengelige containere med Apache Kafka. For ti \u00e5r siden ville dette v\u00e6rt en innovasjon, n\u00e5 er det hverdagskost. Tilsvarende med Static Content Hosting: p\u00e5 grunn av mer brukervennlige teknologier (blant annet fordi det finnes omfattende dokumentasjon og et stort svargrunnlag), har en slik tiln\u00e6rming blitt enda enklere.<\/p>\n<p><\/p>\n<p>Som et resultat har implementeringen av en rekke ganske kompliserte arkitektoniske m\u00f8nstre n\u00e5 blitt mye enklere, noe som betyr at det er klokt \u00e5 se n\u00e6rmere p\u00e5 dem p\u00e5 forh\u00e5nd. Hvis et ti \u00e5r gammelt program forlot en av l\u00f8sningene nevnt ovenfor p\u00e5 grunn av h\u00f8ye kostnader ved implementering og drift, kan man n\u00e5 i et nytt program eller etter refaktorering lage en tjeneste som allerede er b\u00e5de skalerbar (med hensyn til ytelse) og klar for nye foresp\u00f8rslene fra kunder (for eksempel for lokalisering av personlig informasjon).<\/p>\n<p><\/p>\n<p>Og det viktigste: vennligst ikke bruk disse tiln\u00e6rmingene hvis du har en enkel applikasjon. Ja, de er vakre og interessante, men for et nettsted med en maksimal trafikk p\u00e5 100 bes\u00f8kende kan man ofte klare seg med en klassisk monolitt (i hvert fall utenfra, innvendig kan alt deles opp 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.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\/no\/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=\"nn_NO\" \/>\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\/no\/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 arkitektoniske m\u00f8nstre | ProHoster","description":"Hei, Habr! I lys av de n\u00e5v\u00e6rende hendelsene p\u00e5 grunn av koronaviruset har en rekke internettjenester f\u00e5tt \u00f8kt belastning.","canonical_url":"https:\/\/prohoster.info\/no\/blog\/administrirovanie\/udobnye-arhitekturnye-patterny","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nn_NO","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\/no\/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\/no\/wp-json\/wp\/v2\/posts\/80035","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/comments?post=80035"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/posts\/80035\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/media\/80036"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/media?parent=80035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/categories?post=80035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/tags?post=80035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}