{"id":35906,"date":"2019-10-31T22:07:29","date_gmt":"2019-10-31T19:07:29","guid":{"rendered":"https:\/\/prohoster.info\/blog\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\/"},"modified":"2019-10-31T22:07:29","modified_gmt":"2019-10-31T19:07:29","slug":"perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","title":{"rendered":"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>I den h\u00e4r artikeln kommer jag att ber\u00e4tta om hur projektet som jag arbetar med har f\u00f6rvandlats fr\u00e5n en stor monolit till en upps\u00e4ttning mikroservicer.<\/p>\n<p>Projektet b\u00f6rjade sin historia f\u00f6r ganska l\u00e4nge sedan, i b\u00f6rjan av 2000-talet. De f\u00f6rsta versionerna skrevs i Visual Basic 6. Med tiden blev det tydligt att utvecklingen p\u00e5 detta spr\u00e5k skulle bli sv\u00e5r att underh\u00e5lla i framtiden, eftersom b\u00e5de IDE och spr\u00e5ket sj\u00e4lv utvecklades l\u00e5ngsamt. I slutet av 2000-talet beslutades det att g\u00e5 \u00f6ver till det mer lovande C#. Den nya versionen skrevs parallellt med f\u00f6rb\u00e4ttringarna av den gamla, och gradvis blev allt mer kod skriven i .NET. Backend i C# var fr\u00e5n b\u00f6rjan inriktad p\u00e5 en tj\u00e4nsteorienterad arkitektur, men under utvecklingen anv\u00e4ndes gemensamma bibliotek med logik, och tj\u00e4nsterna k\u00f6rdes i en och samma process. Resultatet blev en applikation som vi kallade \"tj\u00e4nstmonolit\". <\/p>\n<p>En av de f\u00e5 f\u00f6rdelarna med denna koppling var m\u00f6jligheten f\u00f6r tj\u00e4nster att anropa varandra via en extern API. Det fanns tydliga tecken p\u00e5 att det var dags att \u00f6verg\u00e5 till en mer korrekt tj\u00e4nste- och s\u00e5 sm\u00e5ningom mikroservicearkitektur. <\/p>\n<p>Vi p\u00e5b\u00f6rjade v\u00e5rt arbete med dekomponering omkring \u00e5r 2015. \u00c4n s\u00e5 l\u00e4nge har vi inte n\u00e5tt ett perfekt tillst\u00e5nd - det finns fortfarande delar av det stora projektet som \u00e4r sv\u00e5ra att kalla monoliter, men de liknar inte heller mikroservicer. Trots detta har framstegen varit betydande. <br \/>\nDetta \u00e4r vad jag ska ber\u00e4tta om i artikeln.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/132bb4ea6b9dbcdd202ee090f2b86289.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Inneh\u00e5ll<\/h3>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#1\"> Arkitektur och problem med nuvarande l\u00f6sning<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#2\">F\u00f6rv\u00e4ntningar p\u00e5 mikroservicer<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#3\">Problem med \u00f6verg\u00e5ngen<\/a><\/noindex><\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"#4\">Hur man g\u00e5r fr\u00e5n monolit till mikroservicer<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#5\">Den f\u00f6rsta metoden<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#6\">Den andra metoden<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#7\">Den tredje metoden<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#8\">Den fj\u00e4rde metoden<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#9\">Arbete med databasen<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#10\">Separera befintliga tabeller<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#11\">Separera med omarbetning<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#12\">Arbete med k\u00e4llkoden<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#13\">Infrastrukturproblem<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#16\">Manuell installation i milj\u00f6er<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#14\">Separat loggning<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#15\">Testning och fels\u00f6kning av relaterade tj\u00e4nster<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><noindex><a rel=\"nofollow\" name=\"1\"><\/a><\/noindex><b><\/p>\n<h3>Arkitektur och problem med nuvarande l\u00f6sning<\/h3>\n<p><\/b><br \/>\nInitialt s\u00e5g arkitekturen ut som f\u00f6ljer: UI - en separat applikation, den monolitiska delen var skriven i Visual Basic 6, och applikationen i .NET var en upps\u00e4ttning relaterade tj\u00e4nster som arbetade med en ganska stor databas.<\/p>\n<p><b>Nackdelar med den tidigare l\u00f6sningen<\/b><\/p>\n<p><u>Ensam felpunkt<\/u><br \/>\nVi hade en enda felpunkt: applikationen p\u00e5 .NET k\u00f6rdes i en process. Om det intr\u00e4ffade ett fel i n\u00e5got av modulerna, stod hela applikationen stilla och fick startas om. Eftersom vi automatiserar ett stort antal processer f\u00f6r olika anv\u00e4ndare, kunde alla inte arbeta under en tid p\u00e5 grund av ett fel i en av dem. Och inget hj\u00e4lpte ens med redundans vid programmeringsfel. <\/p>\n<p><u>K\u00f6 f\u00f6r f\u00f6rb\u00e4ttringar<\/u><br \/>\nDenna brist \u00e4r snarare organisatorisk. I v\u00e5r applikation har vi m\u00e5nga best\u00e4llare, och alla vill ha sina f\u00f6rb\u00e4ttringar s\u00e5 snabbt som m\u00f6jligt. Tidigare var det om\u00f6jligt att g\u00f6ra detta parallellt, och alla best\u00e4llare hamnade i k\u00f6. Denna process skapade negativitet f\u00f6r aff\u00e4rerna, eftersom de beh\u00f6vde bevisa att deras uppgift hade v\u00e4rde. Utvecklingsteamet spenderade tid p\u00e5 att organisera denna k\u00f6. Det tog mycket tid och kraft, och produkten kunde i slut\u00e4ndan inte f\u00f6r\u00e4ndras s\u00e5 snabbt som man hade velat.<\/p>\n<p><u>Ineffektivt resursutnyttjande<\/u><br \/>\nVid placering av tj\u00e4nster i en enskild process kopierade vi alltid helt konfigurationen fr\u00e5n server till server. Vi ville placera de mest belastade tj\u00e4nsterna separat f\u00f6r att inte sl\u00f6sa resurser och f\u00e5 mer flexibel hantering av v\u00e5r distributionsschema.<\/p>\n<p><u>Sv\u00e5rt att implementera moderna teknologier<\/u><br \/>\nEn bekant problem f\u00f6r alla utvecklare: det finns en vilja att inf\u00f6ra moderna teknologier i projektet, men ingen m\u00f6jlighet. Med en stor monolitisk l\u00f6sning blir varje uppdatering av den nuvarande biblioteket, f\u00f6r att inte tala om \u00f6verg\u00e5ngen till en ny, en ganska intressant uppgift. Man m\u00e5ste l\u00e4nge \u00f6vertyga teamledaren om att det kommer att ge fler f\u00f6rdelar \u00e4n de nervfrustrationer som det kostar. <\/p>\n<p><u>Komplexitet vid leverans av f\u00f6r\u00e4ndringar<\/u><br \/>\nDetta var det mest allvarliga problemet - vi gjorde sl\u00e4pp vartannat m\u00e5nad. <br \/>\nVarje sl\u00e4pp blev en riktig katastrof f\u00f6r banken, trots testning och utvecklarnas insatser. Aff\u00e4rerna f\u00f6rstod att en del av funktionaliteten inte skulle fungera i b\u00f6rjan av veckan. Utvecklarna ins\u00e5g att de skulle m\u00f6ta en vecka av allvarliga incidenter. <br \/>\n\u00d6nskan att f\u00f6r\u00e4ndra situationen fanns hos alla. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"2\"><\/a><\/noindex><b><\/p>\n<h3>F\u00f6rv\u00e4ntningar p\u00e5 mikroservicer<\/h3>\n<p><\/b><br \/>\n<u>Leverans av komponenter efter beredskap. <\/u>Leverans av komponenter efter beredskap tack vare deskomposition av l\u00f6sningen och separation av olika processer.<\/p>\n<p><u>Sm\u00e5 produktteam.<\/u> Detta \u00e4r viktigt eftersom det \u00e4r sv\u00e5rt att hantera ett stort team som arbetar med en gammal monolit. Ett s\u00e5dant team m\u00e5ste f\u00f6lja en strikt process, men det skulle vara b\u00e4ttre att f\u00e5 mer kreativitet och oberoende. Det \u00e4r n\u00e5got som endast sm\u00e5 team kan till\u00e5ta sig.<\/p>\n<p><u>Isolering av tj\u00e4nster i separata processer.<\/u> Idealiskt skulle vi vilja isolera i containrar, men m\u00e5nga tj\u00e4nster skrivna p\u00e5 .NET Framework k\u00f6rs endast under Windows. Det kommer nu tj\u00e4nster p\u00e5 .NET Core, men de \u00e4r fortfarande f\u00e5.<\/p>\n<p><u>Flexibilitet i distribution.<\/u> Vi skulle vilja kombinera tj\u00e4nsterna som vi beh\u00f6ver, snarare \u00e4n att g\u00f6ra det som koden tvingar oss till.<\/p>\n<p><u>Anv\u00e4ndning av nya teknologier.<\/u> Detta \u00e4r intressant f\u00f6r varje programmerare.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"3\"><\/a><\/noindex><b><\/p>\n<h3>Problem med \u00f6verg\u00e5ngen<\/h3>\n<p><\/b><br \/>\nNaturligtvis, om det vore enkelt att bryta ner en monolit i mikrotj\u00e4nster, skulle vi inte beh\u00f6va diskutera detta p\u00e5 konferenser eller skriva artiklar. Det finns m\u00e5nga fallgropar i denna process, och jag kommer att beskriva de viktigaste som har hindrat oss.<\/p>\n<p><b>Det f\u00f6rsta problemet<\/b> \u00e4r typiskt f\u00f6r de flesta monoliter: kopplingen av aff\u00e4rslogik. N\u00e4r vi skriver en monolit vill vi \u00e5teranv\u00e4nda v\u00e5ra klasser f\u00f6r att inte skriva \u00f6verfl\u00f6dig kod. Men n\u00e4r man g\u00e5r \u00f6ver till mikrotj\u00e4nster blir det ett problem: all kod \u00e4r ganska strikt kopplad, vilket g\u00f6r det sv\u00e5rt att dela upp tj\u00e4nster.<\/p>\n<p>Vid b\u00f6rjan av arbetet fanns det mer \u00e4n 500 projekt i f\u00f6rvaret och \u00f6ver 700 000 rader kod. Det \u00e4r en ganska stor l\u00f6sning och <b>det andra problemet<\/b>. Att bara ta och dela upp det i mikrotj\u00e4nster var inte m\u00f6jligt.<\/p>\n<p><b>Det tredje problemet<\/b> \u00e4r avsaknaden av n\u00f6dv\u00e4ndig infrastruktur. Faktum \u00e4r att vi h\u00f6ll p\u00e5 med manuell kopiering av k\u00e4llkod till servrar.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"4\"><\/a><\/noindex><b><\/p>\n<h3>Hur man g\u00e5r fr\u00e5n monolit till mikroservicer<\/h3>\n<p><\/b><br \/>\n<u>Utv\u00e4ljning av mikrotj\u00e4nster<\/u><\/p>\n<p>F\u00f6r det f\u00f6rsta definierade vi omg\u00e5ende att uppdelningen av mikrotj\u00e4nster \u00e4r en iterativ process. Vi beh\u00f6vde alltid parallellt arbeta med utvecklingen av aff\u00e4rsuppgifter. Hur vi skulle genomf\u00f6ra detta tekniskt var v\u00e5r problematik. D\u00e4rf\u00f6r var vi f\u00f6rberedda p\u00e5 en iterativ process. Det g\u00e5r inte p\u00e5 n\u00e5got annat s\u00e4tt om du har en stor applikation, och den fr\u00e5n b\u00f6rjan inte \u00e4r redo att skrivas om.<\/p>\n<p>Vilka metoder anv\u00e4nder vi f\u00f6r att v\u00e4lja ut mikrotj\u00e4nster?<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"5\"><\/a><\/noindex><b>Den f\u00f6rsta metoden <\/b>\u2014 att extrahera befintliga moduler som tj\u00e4nster. I det avseendet hade vi tur: det fanns redan etablerade tj\u00e4nster som arbetade enligt WCF-protokollet. De var spridda \u00f6ver separata samlingar. Vi \u00f6verf\u00f6rde dem separat, och lade till en liten startmodul till varje samling. Den var skriven med hj\u00e4lp av det fantastiska biblioteket Topshelf, som g\u00f6r det m\u00f6jligt att k\u00f6ra applikationen b\u00e5de som en tj\u00e4nst och som en konsol. Detta \u00e4r praktiskt f\u00f6r fels\u00f6kning, eftersom det inte kr\u00e4ver n\u00e5gra extra projekt i l\u00f6sningen.<\/p>\n<p>Tj\u00e4nsterna var kopplade av aff\u00e4rslogik, eftersom de anv\u00e4nde gemensamma samlingar och arbetade med en gemensam databas. De var sv\u00e5ra att kalla mikrotj\u00e4nster i strikt bem\u00e4rkelse. Trots detta kunde vi leverera dessa tj\u00e4nster separat, i olika processer. Detta minskade redan deras p\u00e5verkan p\u00e5 varandra och reducerade problem med parallell utveckling och en enda punkt f\u00f6r fel.<\/p>\n<p>Samlingen med v\u00e4rden \u00e4r endast en rad kod i Program-klassen. Arbetet med Topshelf har vi g\u00f6mt i en hj\u00e4lptklass.<\/p>\n<pre><code class=\"plaintext\">namespace RBA.Services.Accounts.Host\n{\n   internal class Program\n   {\n      private static void Main(string[] args)\n      {\n        HostRunner.Run(\"RBA.Services.Accounts.Host\");\n\n       }\n    }\n}\n<\/code><\/pre>\n<p>\n<noindex><a rel=\"nofollow\" name=\"6\"><\/a><\/noindex><b>Den andra metoden f\u00f6r att isolera mikrotj\u00e4nster:<\/b> att skapa dem f\u00f6r att l\u00f6sa nya problem. Om monoliten inte v\u00e4xer under tiden, \u00e4r det redan utm\u00e4rkt, vilket betyder att vi r\u00f6r oss i r\u00e4tt riktning. F\u00f6r att l\u00f6sa nya problem str\u00e4var vi efter att g\u00f6ra separata tj\u00e4nster. Om det finns en m\u00f6jlighet skapar vi mer \"kanoniska\" tj\u00e4nster som helt styr sin datamodell och har en separat databas. <\/p>\n<p>Vi, precis som m\u00e5nga andra, b\u00f6rjade med autentisering och auktoriseringstj\u00e4nster. De passar perfekt f\u00f6r detta. De \u00e4r oberoende och har i regel en avskild datamodell. De interagerar inte med monoliten, utan endast monoliten v\u00e4nder sig till dem f\u00f6r att l\u00f6sa vissa uppgifter. P\u00e5 dessa tj\u00e4nster kan man b\u00f6rja \u00f6verg\u00e5ngen till en ny arkitektur, fels\u00f6ka infrastrukturen och testa olika metoder relaterade till n\u00e4tverksbibliotek, etc. I v\u00e5r organisation finns det inga team som inte skulle kunna skapa en autentiseringstj\u00e4nst. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"7\"><\/a><\/noindex><b>Den tredje metoden f\u00f6r att isolera mikrotj\u00e4nster<\/b>, som vi anv\u00e4nder, \u00e4r n\u00e5got specifikt f\u00f6r oss. Det handlar om att separera aff\u00e4rslogik fr\u00e5n UI-lagret. V\u00e5r huvudsakliga UI-applikation \u00e4r desktop-baserad, och den, precis som backend, \u00e4r skriven i C#. Utvecklarna g\u00f6r ibland misstag och flyttar logik till UI som borde finnas i backend och \u00e5teranv\u00e4ndas. <\/p>\n<p>Om vi tittar p\u00e5 ett verkligt exempel fr\u00e5n koden i UI-delen, s\u00e5 ser vi att en stor del av denna l\u00f6sning inneh\u00e5ller verklig aff\u00e4rslogik som \u00e4r anv\u00e4ndbar i andra processer, inte bara f\u00f6r att bygga UI-formul\u00e4r. <\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/74c7b90ff94b343816ab3ac2fa0673c6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDen verkliga logiken i UI best\u00e5r bara av de senaste par raderna. Vi flyttade den till servern f\u00f6r att kunna \u00e5teranv\u00e4nda den, vilket minskar UI och uppn\u00e5r en korrekt arkitektur.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"8\"><\/a><\/noindex><b>Det fj\u00e4rde och viktigaste s\u00e4ttet att isolera mikrotj\u00e4nster<\/b>, vilket g\u00f6r att man kan minska monoliten, \u00e4r att flytta befintliga tj\u00e4nster med omarbetning. N\u00e4r vi tar ut befintliga moduler som de \u00e4r, \u00e4r resultatet inte alltid tillfredsst\u00e4llande f\u00f6r utvecklarna, och aff\u00e4rsprocessen kan ha blivit f\u00f6r\u00e5ldrad sedan funktionaliteten skapades. Genom refaktorering kan vi st\u00f6dja den nya aff\u00e4rsprocessen, eftersom aff\u00e4rskraven st\u00e4ndigt f\u00f6r\u00e4ndras. Vi kan f\u00f6rb\u00e4ttra koden, ta bort k\u00e4nda defekter och skapa en mer kvalitativ datamodell. M\u00e5nga f\u00f6rdelar byggs upp.<\/p>\n<p>Separeringen av tj\u00e4nster med omarbetning \u00e4r o\u00e5terkalleligt kopplad till begreppet begr\u00e4nsad kontext. Detta \u00e4r ett begrepp inom dom\u00e4norienterad design. Det inneb\u00e4r ett segment av dom\u00e4nmodellen d\u00e4r alla termer i ett gemensamt spr\u00e5k \u00e4r entydigt definierade. L\u00e5t oss ta exempelvis kontexten av f\u00f6rs\u00e4kringar och fakturor. Vi har en monolitisk applikation och beh\u00f6ver arbeta med fakturan i f\u00f6rs\u00e4kringarna. Vi f\u00f6rv\u00e4ntar oss att utvecklaren hittar en redan existerande klass, 'Faktura', i en annan samling, g\u00f6r en referens till den fr\u00e5n klassen 'F\u00f6rs\u00e4kring', och vi f\u00e5r fungerande kod. DRY-principen kommer att f\u00f6ljas, och uppgiften kan genom att anv\u00e4nda befintlig kod utf\u00f6ras snabbare.<\/p>\n<p>Det visar sig att kontexter f\u00f6r konton och f\u00f6rs\u00e4kringar \u00e4r sammankopplade. N\u00e4r nya krav dyker upp kommer denna koppling att f\u00f6rsv\u00e5ra utvecklingen och \u00f6ka komplexiteten i den redan komplicerade aff\u00e4rslogiken. F\u00f6r att l\u00f6sa detta problem m\u00e5ste man i koden identifiera gr\u00e4nserna mellan kontexterna och \u00e5tg\u00e4rda deras \u00f6vertr\u00e4delser. Till exempel, f\u00f6r f\u00f6rs\u00e4kringskontexten kan det mycket v\u00e4l vara tillr\u00e4ckligt med ett 20-siffrigt konto-nummer fr\u00e5n Centralbanken och kontots \u00f6ppningsdatum. <\/p>\n<p>F\u00f6r att separera dessa begr\u00e4nsade kontexter fr\u00e5n varandra och inleda processen med att extrahera mikrotj\u00e4nster fr\u00e5n den monolitiska l\u00f6sningen anv\u00e4nde vi en metod som involverar att skapa externa API:er inom applikationen. Om vi visste att en viss modul skulle bli en mikrotj\u00e4nst, eller f\u00f6r\u00e4ndras p\u00e5 n\u00e5got s\u00e4tt i processen, gjorde vi omedelbart anrop till logik som tillh\u00f6rde en annan begr\u00e4nsad kontext via externa anrop. Till exempel, via REST eller WCF.<\/p>\n<p>Vi har beslutat att inte undvika kod som kr\u00e4ver distribuerade transaktioner. I v\u00e5rt fall har det visat sig vara ganska enkelt att f\u00f6lja denna regel. Vi har fortfarande inte st\u00f6tt p\u00e5 situationer d\u00e4r strikta distribuerade transaktioner verkligen har beh\u00f6vts \u2014 det har varit tillr\u00e4ckligt med slutlig konsistens mellan modulerna.<\/p>\n<p>L\u00e5t oss betrakta ett konkret exempel. Vi har begreppet orkestrator \u2014 en kedja som hanterar entiteten \"ans\u00f6kan\". Den skapar successivt en kund, ett konto och ett bankkort. Om kunden och kontot skapas framg\u00e5ngsrikt men skapandet av kortet misslyckas, g\u00e5r ans\u00f6kan inte till statusen \"framg\u00e5ngsrik\" och f\u00f6rblir i statusen \"kortet skapades inte\". I framtiden kommer bakgrundsaktiviteten att plocka upp den och avsluta den. Systemet f\u00f6rblir under en tid i ett tillst\u00e5nd av inkonsistens, men det \u00e4r vi i stort sett n\u00f6jda med.<\/p>\n<p>I h\u00e4ndelse av att en situation uppst\u00e5r d\u00e4r det beh\u00f6vs en konsekvent bevarande av en del av data, kommer vi troligen att g\u00e5 mot en sammanslagning av tj\u00e4nsten f\u00f6r att behandla detta i en enda process. <\/p>\n<p>L\u00e5t oss betrakta ett exempel p\u00e5 att extrahera en mikrotj\u00e4nst. Hur kan vi relativt s\u00e4kert f\u00f6ra den till produktion? I detta exempel har vi en separat del av systemet \u2014 modulen f\u00f6r l\u00f6nebehandling, en del av koden som vi skulle vilja g\u00f6ra till en mikrotj\u00e4nst.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/346af271b0c3f99897d330e56f713f18.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nF\u00f6rst skapar vi en mikrotj\u00e4nst genom att skriva om koden. Vi f\u00f6rb\u00e4ttrar n\u00e5gra aspekter som vi inte var n\u00f6jda med. Vi implementerar nya aff\u00e4rskrav fr\u00e5n kunden. Vi l\u00e4gger till en API Gateway i kopplingen mellan UI och backend, som ska m\u00f6jligg\u00f6ra vidarebefordran av anrop. <\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/bec8d68f20f3ec53af0cef225a51c2b3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nD\u00e4refter sl\u00e4pper vi denna konfiguration i produktion, men i pilotl\u00e4ge. De flesta av v\u00e5ra anv\u00e4ndare arbetar fortfarande med de gamla aff\u00e4rsprocesserna. F\u00f6r nya anv\u00e4ndare utvecklar vi en ny version av den monolitiska applikationen, som inte l\u00e4ngre inneh\u00e5ller denna process. I princip fungerar v\u00e5rt pilotprojekt som en koppling mellan monoliten och mikrotj\u00e4nsten.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/27e98812746bb7f142fa3a3c3a03b52f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVid en framg\u00e5ngsrik pilot f\u00f6rst\u00e5r vi att den nya konfigurationen faktiskt fungerar, och vi kan ta bort den gamla monoliten och l\u00e5ta den nya konfigurationen ers\u00e4tta den gamla l\u00f6sningen.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/11dcf1d771b57d3921c0aa91b82646e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSumma summarum anv\u00e4nder vi praktiskt taget alla befintliga metoder f\u00f6r att separera koden fr\u00e5n monoliten. Alla dessa metoder g\u00f6r att vi kan minska storleken p\u00e5 delar av applikationen och flytta dem till nya bibliotek, vilket ger en mer kvalitativ kod.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"9\"><\/a><\/noindex><b><\/p>\n<h3>Arbete med databasen<\/h3>\n<p><\/b><br \/>\nDatabasen \u00e4r sv\u00e5rare att dela upp \u00e4n koden, eftersom den inneh\u00e5ller inte bara den aktuella strukturen utan ocks\u00e5 insamlade historiska data.<\/p>\n<p>V\u00e5r databas, precis som m\u00e5nga andra, hade ytterligare en viktig nackdel - den enorma storleken. Denna databas designades enligt den komplicerade aff\u00e4rslogiken i monoliten, och mellan tabellerna av olika begr\u00e4nsade sammanhang har det uppst\u00e5tt kopplingar.<\/p>\n<p>I v\u00e5rt fall, f\u00f6r att l\u00e4gga till allt detta (stor databas, m\u00e5nga relationer, ibland oklara gr\u00e4nser mellan tabeller), uppstod ett problem som f\u00f6rekommer i m\u00e5nga stora projekt: anv\u00e4ndningen av m\u00f6nstret f\u00f6r delad databas. Data h\u00e4mtades fr\u00e5n tabeller via vyer, genom replikering och skickades till andra system d\u00e4r denna replikering beh\u00f6vdes. Som ett resultat kunde vi inte separera tabellerna i en egen struktur, eftersom de aktivt anv\u00e4ndes.<\/p>\n<p>I separationen hj\u00e4lper oss sj\u00e4lva uppdelningen i begr\u00e4nsade sammanhang i koden. Detta ger i allm\u00e4nhet en ganska bra bild av hur vi delar upp data p\u00e5 databaseniv\u00e5. Vi f\u00f6rst\u00e5r vilka tabeller som tillh\u00f6r ett begr\u00e4nsat sammanhang och vilka som tillh\u00f6r ett annat.<\/p>\n<p>Vi har till\u00e4mpat tv\u00e5 globala metoder f\u00f6r att separera databasen: separation av befintliga tabeller och separation med omarbetning.<\/p>\n<p>Separation av befintliga tabeller \u00e4r en metod som fungerar bra n\u00e4r datakonstruktionen \u00e4r av h\u00f6g kvalitet, uppfyller aff\u00e4rskrav och alla \u00e4r n\u00f6jda. I detta fall kan vi s\u00e4rskilja befintliga tabeller till ett eget schema.<\/p>\n<p>Separation med omarbetning beh\u00f6vs n\u00e4r aff\u00e4rsmodellen har f\u00f6r\u00e4ndrats kraftigt, och tabellerna l\u00e4ngre inte tillfredsst\u00e4ller v\u00e5ra behov.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"10\"><\/a><\/noindex><b>Separation av befintliga tabeller.<\/b> Vi beh\u00f6ver definiera vad vi ska separera. Utan denna kunskap kan vi inte lyckas, och h\u00e4r kan separation av begr\u00e4nsade kontexter i koden hj\u00e4lpa oss. Om man vanligtvis kan f\u00f6rst\u00e5 gr\u00e4nserna f\u00f6r kontexterna i koden, blir det klart vilka tabeller som m\u00e5ste ing\u00e5 i listan f\u00f6r separation.<\/p>\n<p>L\u00e5t oss f\u00f6rest\u00e4lla oss att vi har en l\u00f6sning d\u00e4r tv\u00e5 moduler i monoliten interagerar med en databas. Vi beh\u00f6ver se till att endast en modul interagerar med den del av tabellerna som ska separeras, medan den andra b\u00f6rjar interagera med den via API. F\u00f6rst \u00e4r det tillr\u00e4ckligt att endast skrivning sker via API. Detta \u00e4r en n\u00f6dv\u00e4ndig f\u00f6ruts\u00e4ttning f\u00f6r att vi ska kunna tala om oberoende mikrotj\u00e4nster. L\u00e4sning kan f\u00f6rbli kopplad s\u00e5 l\u00e4nge det inte orsakar n\u00e5gra stora problem.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/1602637ad752ac055f475cfa45d95e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nI n\u00e4sta steg kan vi redan separera koden som arbetar med de separerade tabellerna, med eller utan omarbetning, till en egen mikrotj\u00e4nst och k\u00f6ra den i en separat process eller container. Det kommer att bli en separat tj\u00e4nst med koppling till monolitens databas och de tabeller som inte direkt tillh\u00f6r den. Monoliten kan fortfarande l\u00e4sa fr\u00e5n den separerade delen. <\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/36011f4e6be4f6a2f19f2f074b645dcb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSenare kommer vi att ta bort denna koppling, vilket betyder att l\u00e4sning av data fr\u00e5n de separerade tabellerna i den monolitiska applikationen ocks\u00e5 kommer att \u00f6verg\u00e5 till API.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/290f91bbfccac2a4b384078e4cf4e337.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nD\u00e4refter kommer vi att separera tabellerna fr\u00e5n den gemensamma databasen som endast den nya mikrotj\u00e4nsten arbetar med. Vi kan flytta tabellerna till ett eget schema eller till och med en egen fysisk databas. Det finns fortfarande en l\u00e4srelation mellan mikrotj\u00e4nsten och monolitens databas, men det \u00e4r inget stort problem; i en s\u00e5dan konfiguration kan den leva ganska l\u00e4nge.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/ab947ac6a38ffbccd4e2b51103aef609.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDet sista steget \u00e4r att helt ta bort alla kopplingar. I det h\u00e4r fallet kan vi beh\u00f6va migrera data fr\u00e5n huvuddatabasen. Ibland vill vi \u00e5teranv\u00e4nda vissa replikerade data eller register fr\u00e5n externa system i flera databaser. Det h\u00e4r intr\u00e4ffar periodiskt hos oss.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/f40cf17dd56b9575751e370c44f08344.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<noindex><a rel=\"nofollow\" name=\"11\"><\/a><\/noindex><b>Avdelning f\u00f6r omarbetning.<\/b> Denna metod liknar den f\u00f6rsta, men g\u00e5r i motsatt ordning. Vi s\u00e4tter omedelbart upp en ny databas och en ny mikrotj\u00e4nst som interagerar med monoliten via API. Men vi beh\u00e5ller en upps\u00e4ttning databastabeller som vi vill ta bort i framtiden. Vi beh\u00f6ver dem inte l\u00e4ngre, i den nya modellen har vi ersatt dem.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/c94932033e47cfa1fd56595ab9a19246.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nF\u00f6r att detta schema ska fungera kommer vi f\u00f6rmodligen att beh\u00f6va en \u00f6verg\u00e5ngsperiod.<\/p>\n<p>Det finns tv\u00e5 m\u00f6jliga tillv\u00e4gag\u00e5ngss\u00e4tt h\u00e4rn\u00e4st.<\/p>\n<p><b>F\u00f6rsta<\/b>: vi duplica all data i den nya och gamla databasen. I detta fall f\u00e5r vi dataduplicering och kan f\u00e5 problem med synkronisering. Men vi kan ha tv\u00e5 olika kunder. En kommer att arbeta med den nya versionen, den andra med den gamla.<\/p>\n<p><b>Den andra<\/b>: vi delar upp data efter n\u00e5got aff\u00e4rskriterium. Till exempel hade vi 5 produkter i v\u00e5rt system som lagrades i den gamla databasen. Den sj\u00e4tte som en del av den nya aff\u00e4rsuppgiften placerar vi i den nya databasen. Men vi beh\u00f6ver en API-gateway som synkroniserar dessa data och visar f\u00f6r kunden varifr\u00e5n och vad som ska tas.<\/p>\n<p>B\u00e5da tillv\u00e4gag\u00e5ngss\u00e4tten fungerar, v\u00e4lj beroende p\u00e5 situationen.<\/p>\n<p>Efter att vi har s\u00e4kerst\u00e4llt att allt fungerar kan vi st\u00e4nga av den del av monoliten som arbetar med de gamla databaskonstruktionerna. <\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/973bf5015bdf49a290a5b901f89628cc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDet sista steget blir att ta bort de gamla datakonstruktionerna. <\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/fe83acc07077b7eb3717138e3c20c005.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSammanfattningsvis kan vi s\u00e4ga att vi har problem med databasen: det \u00e4r sv\u00e5rare att arbeta med den j\u00e4mf\u00f6rt med k\u00e4llkoden, det \u00e4r sv\u00e5rare att dela upp, men det kan och m\u00e5ste g\u00f6ras. Vi har funnit n\u00e5gra s\u00e4tt som g\u00f6r att vi kan g\u00f6ra det tillr\u00e4ckligt s\u00e4kert, eftersom det \u00e4r l\u00e4gre sannolikhet att g\u00f6ra misstag med data \u00e4n med k\u00e4llkoden. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"12\"><\/a><\/noindex><b><\/p>\n<h3>Arbete med k\u00e4llkoden<\/h3>\n<p><\/b><br \/>\nS\u00e5 h\u00e4r s\u00e5g k\u00e4llkodsdiagrammet ut n\u00e4r vi b\u00f6rjade analysera det monolitiska projektet.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/a6d886e37117ccf8f63106d6616aa653.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDen kan uppdelas i tre lager. Det \u00e4r lagret f\u00f6r k\u00f6rbara moduler, plugins, tj\u00e4nster och specifika aktiviteter. Faktiskt var dessa ing\u00e5ngspunkter inuti den monolitiska l\u00f6sningen. Alla var fast f\u00f6rankrade i lagret Common. H\u00e4r fanns den aff\u00e4rslogik som anv\u00e4ndes gemensamt av tj\u00e4nsterna, och massor av kopplingar. Varje tj\u00e4nst och plugin anv\u00e4nde upp till 10 eller fler common-assemblies, beroende p\u00e5 deras storlek och utvecklarnas samvete.<\/p>\n<p>Vi hade tur, vi hade infrastrukturbibliotek som kunde anv\u00e4ndas separat. <\/p>\n<p>Ibland uppstod situationer d\u00e4r vissa Common-objekt faktiskt inte tillh\u00f6rde detta lager, utan var infrastrukturbibliotek. Detta l\u00f6stes genom att byta namn.<\/p>\n<p>Det som st\u00f6rde mest var de begr\u00e4nsade kontexterna. Det h\u00e4nde att 3-4 kontexter blandades i en och samma Common-assembly och anv\u00e4nde varandra inom samma aff\u00e4rsfunktioner. Det var n\u00f6dv\u00e4ndigt att f\u00f6rst\u00e5 var detta kunde delas och vid vilka gr\u00e4nser, samt vad som skulle g\u00f6ras med mappningen av denna delning p\u00e5 k\u00e4llkodens assemblies.<\/p>\n<p>Vi formulerade flera regler f\u00f6r kodseparationsprocessen.<\/p>\n<p><b>F\u00f6rsta<\/b>: vi ville inte l\u00e4ngre dela aff\u00e4rslogik mellan tj\u00e4nster, aktiviteter och plugins. Vi ville g\u00f6ra aff\u00e4rslogiken oberoende inom mikrotj\u00e4nster. \u00c5 andra sidan uppfattas mikrotj\u00e4nster, i en perfekt v\u00e4rld, som tj\u00e4nster som finns helt oberoende. Jag anser att detta tillv\u00e4gag\u00e5ngss\u00e4tt \u00e4r n\u00e5got sl\u00f6saktigt, och att uppn\u00e5 det \u00e4r sv\u00e5rt, eftersom till exempel tj\u00e4nster i C# alltid kommer att kopplas samman med standardbiblioteket. V\u00e5rt system \u00e4r skrivet i C#, och vi har inte beh\u00f6vt anv\u00e4nda andra teknologier hittills. D\u00e4rf\u00f6r beslutade vi att vi kan till\u00e5ta oss att anv\u00e4nda gemensamma tekniska assemblies. Det viktigaste \u00e4r att de inte inneh\u00e5ller n\u00e5gra fragment av aff\u00e4rslogik. Om du har en praktisk wrapper \u00f6ver ORM:en du anv\u00e4nder, \u00e4r det v\u00e4ldigt kostsamt att kopiera den fr\u00e5n tj\u00e4nst till tj\u00e4nst.<\/p>\n<p>V\u00e5rt team \u00e4r fans av dom\u00e4norienterad design, s\u00e5 \"l\u00f6karkitektur\" passade oss perfekt. Grunden i v\u00e5ra tj\u00e4nster blev inte data\u00e5tkomstskiktet, utan en samling med dom\u00e4nlogik, som inneh\u00e5ller enbart aff\u00e4rslogik och saknar kopplingar till infrastrukturen. P\u00e5 s\u00e5 s\u00e4tt kan vi oberoende vidareutveckla dom\u00e4nsamlingen f\u00f6r att l\u00f6sa problem relaterade till ramverk.<\/p>\n<p>Vid detta stadium st\u00f6tte vi p\u00e5 det f\u00f6rsta allvarliga problemet. Tj\u00e4nsten skulle h\u00e4nvisa till en dom\u00e4nsamling, vi ville g\u00f6ra logiken oberoende, och h\u00e4r f\u00f6rsv\u00e5rade principen DRY oss. Utvecklarna ville f\u00f6r att undvika duplicering \u00e5teranv\u00e4nda klasser fr\u00e5n angr\u00e4nsande samlingar, och som ett resultat b\u00f6rjade dom\u00e4nerna \u00e5terigen att kopplas samman. Vi analyserade resultaten och beslutade att problemet \u00e4ven kunde ligga inom hur lagringen av k\u00e4llkoden var organiserad. Vi hade ett stort repository d\u00e4r all k\u00e4llkod l\u00e5g. L\u00f6sningen f\u00f6r hela projektet var mycket sv\u00e5r att s\u00e4tta ihop p\u00e5 en lokal maskin. D\u00e4rf\u00f6r skapades separata sm\u00e5 l\u00f6sningar f\u00f6r projektets delar, och ingen hindrade oss fr\u00e5n att l\u00e4gga till en gemensam eller dom\u00e4nsamling och \u00e5teranv\u00e4nda dem. Det enda verktyget som hindrade oss fr\u00e5n att g\u00f6ra detta var kodgranskningen. Men ibland sviktade \u00e4ven det.<\/p>\n<p>D\u00e5 b\u00f6rjade vi \u00f6verg\u00e5 till en modell med separata repository. Aff\u00e4rslogiken slutade att l\u00e4cka fr\u00e5n tj\u00e4nst till tj\u00e4nst, dom\u00e4nerna blev verkligen oberoende. Begr\u00e4nsade kontexter st\u00f6ds tydligare. Hur \u00e5teranv\u00e4nder vi infrastrukturomr\u00e5dets bibliotek? Vi isolerade dem i ett eget repository, sedan placerade vi dem i Nuget-paket som vi la i Artifactory. Vid varje \u00e4ndring sker bygget och publiceringen automatiskt.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/8ddbc750dc7c6d397a459acf7825de90.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nV\u00e5ra tj\u00e4nster b\u00f6rjade h\u00e4nvisa till inre infrastrukturbibliotek p\u00e5 samma s\u00e4tt som till externa. Vi laddar ner externa bibliotek fr\u00e5n Nuget. F\u00f6r att arbeta med Artifactory, dit vi placerade dessa paket, anv\u00e4nde vi tv\u00e5 paketchefer. I sm\u00e5 repository anv\u00e4nde vi ocks\u00e5 Nuget. I repository med flera tj\u00e4nster anv\u00e4nde vi Paket, som ger mer \u00f6verensst\u00e4mmelse i versionerna mellan moduler.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/672a25a70a481bff68baebe963184ccd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nGenom att arbeta med k\u00e4llkoden, g\u00f6ra sm\u00e5 \u00e4ndringar i arkitekturen och separera repositorier, g\u00f6r vi v\u00e5ra tj\u00e4nster mer oberoende.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"13\"><\/a><\/noindex><b><\/p>\n<h3>Infrastrukturproblem<\/h3>\n<p><\/b><br \/>\nDe flesta nackdelar vid \u00f6verg\u00e5ngen till mikrotj\u00e4nster \u00e4r relaterade till infrastrukturen. Du kommer att beh\u00f6va automatiserad distribuition och nya bibliotek f\u00f6r att hantera infrastrukturen.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"16\"><\/a><\/noindex><b>Manuell installation i milj\u00f6er<\/b><\/p>\n<p>Fr\u00e5n b\u00f6rjan installerade vi milj\u00f6erna manuellt. F\u00f6r att automatisera denna process skapade vi en CI\/CD-pipeline. Vi valde processen continuous delivery eftersom continuous deployment fortfarande inte \u00e4r acceptabelt f\u00f6r oss n\u00e4r det g\u00e4ller aff\u00e4rsprocesser. D\u00e4rf\u00f6r skickas distributionen i produktion med en knapptryckning, medan testningen sker automatiskt.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/0fc092326a48813398c6f3a031197bab.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVi anv\u00e4nder Atlassian, Bitbucket f\u00f6r att lagra k\u00e4llkoder och Bamboo f\u00f6r byggning. Vi gillar att skriva byggskrift p\u00e5 Cake eftersom det \u00e4r samma som C#. I Artifactory kommer redan f\u00e4rdiga paket, och Ansible skickas automatiskt till testservrar, d\u00e4refter kan de testas direkt.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/fcc743cfaa4a24b906ceeb40ec1ba0a0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<noindex><a rel=\"nofollow\" name=\"14\"><\/a><\/noindex><b><\/p>\n<h3>Separat loggning<\/h3>\n<p><\/b><br \/>\nVid en tidpunkt var en av id\u00e9erna bakom monoliten att s\u00e4kerst\u00e4lla gemensam loggning. Vi beh\u00f6vde ocks\u00e5 f\u00f6rst\u00e5 vad vi skulle g\u00f6ra med separata loggar som ligger p\u00e5 diskar. V\u00e5ra loggar skrivs till textfiler. Vi beslutade att anv\u00e4nda den standardiserade ELK-stacken. Vi valde att inte skriva direkt till ELK genom leverant\u00f6rer, utan best\u00e4mde oss f\u00f6r att f\u00f6rb\u00e4ttra textloggarna och registrera sp\u00e5r-ID:n som identifikatorer, plus att tillf\u00f6ra tj\u00e4nstens namn s\u00e5 att dessa loggar senare kunde analyseras.<\/p>\n<p><img decoding=\"async\" alt=\"\u00d6verg\u00e5ngen fr\u00e5n monolit till mikrotj\u00e4nster: historia och praktik\" src=\"\/wp-content\/uploads\/2019\/07\/8e58c66ac134e65abe34b59939f31483.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMed hj\u00e4lp av Filebeat f\u00e5r vi m\u00f6jlighet att samla v\u00e5ra loggar fr\u00e5n <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/sv\/server\/\"   title=\"servrar\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1338\">servrar<\/a>, och sedan bearbeta dem, anv\u00e4nda Kibana f\u00f6r att bygga f\u00f6rfr\u00e5gningar i UI och se hur anropet mellan tj\u00e4nsterna har g\u00e5tt. H\u00e4r hj\u00e4lper sp\u00e5r-ID:n mycket.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"15\"><\/a><\/noindex><b><\/p>\n<h3>Testning och fels\u00f6kning av relaterade tj\u00e4nster<\/h3>\n<p><\/b><br \/>\nTill en b\u00f6rjan f\u00f6rstod vi inte helt hur vi skulle debugga de utvecklade tj\u00e4nsterna. Med monoliten var det enkelt, vi k\u00f6rde den p\u00e5 v\u00e5r lokala maskin. Vi f\u00f6rs\u00f6kte f\u00f6rst g\u00f6ra likadant med mikrotj\u00e4nster, men ibland kr\u00e4vs det att man startar flera andra tj\u00e4nster f\u00f6r att en enda mikrotj\u00e4nst ska fungera, vilket \u00e4r opraktiskt. Vi ins\u00e5g att vi beh\u00f6vde \u00f6verg\u00e5 till en modell d\u00e4r vi bara l\u00e4mnar tj\u00e4nsten eller tj\u00e4nsterna vi vill debugga p\u00e5 v\u00e5r lokala maskin. De andra tj\u00e4nsterna anv\u00e4nds fr\u00e5n servrar som \u00f6verensst\u00e4mmer med konfigurationen p\u00e5 produktion. Efter debuggningsfasen, vid testning, levereras bara de \u00e4ndrade tj\u00e4nsterna till testservern f\u00f6r varje uppgift. P\u00e5 s\u00e5 s\u00e4tt testas l\u00f6sningen i den form den kommer att ha p\u00e5 produktion i framtiden.<\/p>\n<p>Vi har servrar som endast har produktionsversioner av tj\u00e4nsterna. Dessa servrar beh\u00f6vs f\u00f6r incidenthantering, f\u00f6r att kontrollera leveransen f\u00f6re distribution och f\u00f6r interna utbildningar.<\/p>\n<p>Vi har lagt till en process f\u00f6r automatisk testning med hj\u00e4lp av det popul\u00e4ra biblioteket Specflow. Tester k\u00f6rs automatiskt med hj\u00e4lp av NUnit direkt efter distribution fr\u00e5n Ansible. Om testningen av en uppgift \u00e4r helt automatisk, beh\u00f6vs ingen manuell testning. \u00c4ven om manuell testning ibland fortfarande kr\u00e4vs. F\u00f6r att avg\u00f6ra vilka tester som ska k\u00f6ras f\u00f6r en specifik uppgift anv\u00e4nder vi taggar i Jira.<\/p>\n<p>Behovet av belastningstestning har ocks\u00e5 \u00f6kat, tidigare genomf\u00f6rdes det endast i s\u00e4llsynta fall. F\u00f6r att k\u00f6ra tester anv\u00e4nder vi JMeter, f\u00f6r att lagra dem anv\u00e4nds InfluxDB, och f\u00f6r att skapa diagram \u00f6ver processen anv\u00e4nds Grafana.<\/p>\n<p><b><\/p>\n<h3>Vad har vi uppn\u00e5tt?<\/h3>\n<p><\/b><br \/>\nF\u00f6r det f\u00f6rsta har vi avskaffat begreppet \"release\". De tv\u00e5 m\u00e5nader l\u00e5nga monstru\u00f6sa releaserna har f\u00f6rsvunnit, d\u00e5 denna stora applikation distribuerades i produktionsmilj\u00f6 och st\u00f6rde aff\u00e4rsprocesserna tillf\u00e4lligt. Nu distribuerar vi tj\u00e4nster i genomsnitt var 1,5 dag, grupperar dem eftersom de s\u00e4tts i drift efter godk\u00e4nnande.<\/p>\n<p>I v\u00e5rt system finns det inga fatala fel. Om vi sl\u00e4pper en mikrotj\u00e4nst med ett fel, kommer funktionaliteten kopplad till detta att vara trasig, men all annan funktionalitet p\u00e5verkas inte. Detta f\u00f6rb\u00e4ttrar anv\u00e4ndarupplevelsen avsev\u00e4rt.<\/p>\n<p>Vi kan hantera distributionsschemat. Det g\u00e5r att separera grupper av tj\u00e4nster fr\u00e5n resten av l\u00f6sningen om det beh\u00f6vs.<\/p>\n<p>Dessutom har vi avsev\u00e4rt minskat problemet med l\u00e5nga k\u00f6er av arbetsuppgifter. Vi har f\u00e5tt separata produktteam som arbetar med en del av tj\u00e4nsterna oberoende. Scrum-processen passar h\u00e4r ganska bra. Ett specifikt team kan ha en egen produkt\u00e4gare som s\u00e4tter upp uppgifter f\u00f6r dem. <\/p>\n<p><b><\/p>\n<h3>Sammanfattning<\/h3>\n<p><\/b><\/p>\n<ul>\n<li>Mikrotj\u00e4nster passar bra f\u00f6r att dekomponera komplexa system. Under processen b\u00f6rjar vi f\u00f6rst\u00e5 vad som finns i v\u00e5rt system, vilka begr\u00e4nsade kontexter som finns, och var deras gr\u00e4nser g\u00e5r. Detta g\u00f6r att vi kan f\u00f6rdela arbetsuppgifter p\u00e5 r\u00e4tt s\u00e4tt mellan modulerna och undvika koden fr\u00e5n att bli f\u00f6rvirrad. <\/li>\n<li>Mikrotj\u00e4nster erbjuder organisatoriska f\u00f6rdelar. Dessa talas ofta om som en arkitektur, men varje arkitektur beh\u00f6vs f\u00f6r att m\u00f6ta aff\u00e4rsbehov, och inte f\u00f6r sin egen skull. D\u00e4rf\u00f6r kan vi s\u00e4ga att mikrotj\u00e4nster passar bra f\u00f6r att l\u00f6sa uppgifter med sm\u00e5 team, med tanke p\u00e5 att Scrum just nu \u00e4r mycket popul\u00e4rt.<\/li>\n<li>Delningen \u00e4r en iterativ process. Man kan inte bara ta en applikation och dela upp den i mikrotj\u00e4nster. Den resulterande produkten kommer sannolikt inte att vara fungerande. N\u00e4r man delar upp mikrotj\u00e4nster \u00e4r det f\u00f6rdelaktigt att skriva om den befintliga legacy-koden, det vill s\u00e4ga att omvandla den till kod som vi gillar och som b\u00e4ttre uppfyller aff\u00e4rens behov av funktionalitet och hastighet.\n<p><i>Ett litet varningstecken:<\/i> kostnaderna f\u00f6r att \u00f6verg\u00e5 till mikrotj\u00e4nster \u00e4r ganska betydande. Det har tagit mycket tid bara att l\u00f6sa infrastrukturomr\u00e5det. S\u00e5 om du har en liten applikation som inte kr\u00e4ver specifik skalning, och om det inte finns ett stort antal kunder som konkurrerar om din teams uppm\u00e4rksamhet och tid, s\u00e5 \u00e4r det m\u00f6jligt att mikrotj\u00e4nster inte \u00e4r vad du beh\u00f6ver idag. Det \u00e4r ganska dyrt. Om man b\u00f6rjar processen med mikrotj\u00e4nster, s\u00e5 kommer kostnaderna i b\u00f6rjan att vara h\u00f6gre \u00e4n om samma projekt b\u00f6rjade med utveckling av en monolit. <\/p>\n<p>P.S. En mer emotionell ber\u00e4ttelse (som om det var personligt till dig) \u2013 om <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=qTNbx18DzpQ\">l\u00e4nken<\/a><\/noindex>. <br \/>\nH\u00e4r \u00e4r hela versionen av rapporten.<\/li>\n<\/ul>\n<p>K\u00e4lla: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/raiffeisenbank\/blog\/458404\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000. \u041f\u0435\u0440\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Visual Basic 6. \u0421 \u0442\u0435\u0447\u0435\u043d\u0438\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430 \u044d\u0442\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a IDE [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":26858,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-35906","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.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000.\" \/>\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\/sv\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sv_SE\" \/>\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\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043e\u0442 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\" \/>\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=\"2019-10-31T19:07:29+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:07:29+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\u00d6verg\u00e5ngen fr\u00e5n monoliten till mikroservicer: historia och praktik | ProHoster","description":"I den h\u00e4r artikeln kommer jag att ber\u00e4tta om hur projektet jag arbetar med har f\u00f6rvandlats fr\u00e5n en stor monolit till en upps\u00e4ttning mikroservicer. Projektet b\u00f6rjade sin historia f\u00f6r ganska l\u00e4nge sedan, i b\u00f6rjan av 2000-talet.","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sv_SE","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\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043e\u0442 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 | ProHoster","og:description":"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000.","og:url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","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":"2019-10-31T19:07:29+00:00","article:modified_time":"2019-10-31T19:07:29+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"35906","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":"2026-02-09 17:04:56","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:54:38","updated":"2026-02-09 17:04:56","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/35906","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=35906"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/35906\/revisions"}],"predecessor-version":[{"id":158582,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/35906\/revisions\/158582"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/26858"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=35906"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=35906"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=35906"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}