An dësem Artikel wÀert ech schwÀtzen iwwer wéi de Projet, un deem ech schaffen, vun engem grousse Monolith an eng Rei vu Mikroservicer transforméiert gouf.
De Projet huet seng Geschicht viru laanger ZÀit ugefaang, Ufank 2000. Déi éischt Versioune goufen a Visual Basic 6 geschriwwen. Mat der ZÀit gouf kloer datt d'Entwécklung an dëser Sprooch an Zukunft schwéier z'ënnerstëtzen, well d'IDE an d'Sprooch selwer sinn schlecht entwéckelt. Um Enn vun den 2000er gouf decidéiert op déi méi villverspriechend C # ze wiesselen. Déi nei Versioun gouf parallel mat der Revisioun vun der aler geschriwwen, no an no gouf ëmmer méi Code am .NET geschriwwe. Backend am C # war am Ufank op eng Servicearchitektur konzentréiert, awer wÀrend der Entwécklung goufen allgemeng Bibliothéike mat Logik benotzt, a Servicer goufen an engem eenzege Prozess lancéiert. D'Resultat war eng Applikatioun déi mir e "Service Monolith" genannt hunn.
Ee vun de wéinege Virdeeler vun dëser Kombinatioun war d'FÀegkeet vu Servicer fir sech duerch eng extern API ze ruffen. Et waren kloer Viraussetzunge fir den Iwwergank zu engem méi korrekt Service, an an Zukunft, Microservice Architektur.
Mir hunn eis Aarbecht un der Zersetzung ëm 2015 ugefaangen. Mir hunn nach net en idealen Zoustand erreecht - et ginn nach Deeler vun engem grousse Projet, déi kaum Monolithen genannt ginn, awer si kucken och net wéi Mikroservicer. Trotzdem ass de Fortschrëtt bedeitend.
Ech wÀert doriwwer am Artikel schwÀtzen.

Inhalt
Architektur a Problemer vun der bestehend Léisung
Am Ufank huet d'Architektur esou ausgesinn: d'UI ass eng separat Applikatioun, de monolitheschen Deel ass a Visual Basic 6 geschriwwen, d'.NET Applikatioun ass eng Rei vu verbonne Servicer déi mat enger zimlech grousser Datebank schaffen.
Nodeeler vun der viregter Léisung
Eenzege Punkt vun Echec
Mir haten een eenzege Punkt vum Echec: d'.NET Applikatioun leeft an engem eenzege Prozess. Wann e Modul gescheitert ass, ass déi ganz Applikatioun gescheitert an huet missen nei gestart ginn. Well mir eng grouss Zuel vu Prozesser fir verschidde Benotzer automatiséieren, wéinst engem Feeler an engem vun hinnen, konnt jidderee fir eng ZÀit net schaffen. An am Fall vun engem Software Feeler, souguer Backupsatellit huet net gehollef.
Schlaang vun Verbesserungen
Dësen Nodeel ass éischter organisatoresch. Eis Applikatioun huet vill Clienten, a si wëllen se all sou séier wéi méiglech verbesseren. Virdrun war et onméiglech dëst parallel ze maachen, an all Clienten stoungen an der Linn. Dëse Prozess war negativ fir d'Entreprisen, well se hu misse beweisen datt hir Aufgab wÀertvoll war. An d'Entwécklungsteam huet ZÀit verbruecht fir dës Schlaang ze organiséieren. Dëst huet vill ZÀit an Effort gedauert, an d'Produkt konnt schlussendlech net sou séier Ànneren wéi se gÀr hÀtten.
Suboptimal Notzung vu Ressourcen
Wa mir Servicer an engem eenzege Prozess hosten, hu mir d'Konfiguratioun ëmmer komplett vu Server op Server kopéiert. Mir wollten déi am meeschte belaaschte Servicer getrennt placéieren fir net Ressourcen ze verschwenden a méi flexibel Kontroll iwwer eis Deployment Schema ze kréien.
Schwiereg modern Technologien ëmzesetzen
E Problem kennt all Entwéckler: et ass e Wonsch modern Technologien an de Projet aféieren, mÀ et gëtt keng Chance. Mat enger grousser monolithescher Léisung gëtt all Aktualiséierung vun der aktueller Bibliothéik, fir net den Iwwergank op eng nei ze ernimmen, an eng zimlech net-trivial Aufgab. Et dauert laang ZÀit fir dem Teamleader ze beweisen datt dëst méi Bonus bréngt wéi verschwenden Nerven.
Schwieregkeeten Ănnerungen erausginn
Dëst war de seriösten Problem - mir hunn all zwee Méint Verëffentlechungen verëffentlecht.
All Verëffentlechung gouf zu enger realer Katastroph fir d'Bank, trotz den Testen an Efforten vun den Entwéckler. D'GeschÀft huet verstanen datt am Ufank vun der Woch e puer vu senge Funktionalitéit net funktionnéiert. An d'Entwéckler hunn verstanen datt eng Woch vu schlëmmen TëschefÀll op si waarden.
Jiddereen hat e Wonsch d'Situatioun ze Ànneren.
Erwaardungen vun microservices
Ausgab vun Komponente wann prett. Liwwerung vu Komponenten wann se prett sinn andeems d'Léisung zerstéiert a verschidde Prozesser trennt.
Kleng Produktteams. Dëst ass wichteg well e grousst Team, deen um alen Monolith geschafft huet, schwéier ze managen war. Esou eng Equipe war gezwongen no engem strikte Prozess ze schaffen, mÀ si wollten méi Kreativitéit an OnofhÀngegkeet. Nëmmen kleng Equipen konnten sech dat leeschten.
Isolatioun vu Servicer a getrennte Prozesser. Am Idealfall géif ech et gÀren a Container isoléieren, awer eng grouss Zuel vu Servicer, déi am .NET Framework geschriwwe sinn, lafen nëmmen ënner ... WindowsServicer baséiert op .NET Core erschéngen elo, awer et gëtt nach ëmmer wéineg dovun.
Deployment Flexibilitéit. Mir wëllen Servicer kombinéieren wéi mir se brauchen, an net wéi de Code et forcéiert.
Notzung vun neien Technologien. Dëst ass interessant fir all Programméierer.
Iwwergangsproblemer
Natierlech, wann et einfach wier e Monolith a Mikroservicer ze briechen, da wier et net néideg doriwwer op Konferenzen ze schwÀtzen an Artikelen ze schreiwen. Et gi vill Falen an dësem Prozess; Ech wÀert déi Haapt beschreiwen, déi eis behënnert hunn.
Den éischte Problem typesch fir déi meescht Monolithen: KohÀrenz vun der GeschÀftslogik. Wa mir e Monolith schreiwen, wëlle mir eis Klassen nei benotzen fir net onnéideg Code ze schreiwen. A wann Dir op Mikroservicer plënnert, gëtt dëst e Problem: all Code ass zimlech enk gekoppelt, an et ass schwéier d'Servicer ze trennen.
Zu der ZÀit vum Start vun der Aarbecht hat de Repository méi wéi 500 Projeten a méi wéi 700 Tausend Codelinnen. Dëst ass eng zimlech grouss Entscheedung an zweete Problem. Et war net méiglech et einfach ze huelen an et a Mikroservicer opzedeelen.
Drëtte Problem - Mangel un néideg Infrastruktur. TatsÀchlech hu mir de Quellcode manuell op d'Server kopéiert.
Wéi vum Monolith op Mikroservicer ze plënneren
Dispositioun vun Microservices
Als éischt hu mir direkt fir eis selwer festgestallt datt d'Trennung vu Mikroservicer en iterative Prozess ass. Mir waren ëmmer verlaangt AffÀr Problemer parallel ze entwéckelen. Wéi mir dat technesch ëmsetzen ass schonn eise Problem. Dofir hu mir op en iterative Prozess virbereet. Et funktionnéiert net op eng aner Manéier wann Dir eng grouss Applikatioun hutt an et ass am Ufank net prett fir nei geschriwwe ze ginn.
Wéi eng Methode benotze mir fir Mikroservicer ze isoléieren?
DĂ©i Ă©ischt ManĂ©ier - rĂ©ckelen bestehend Moduler als Servicer. An dĂ«ser Hisiicht ware mir GlĂ©ck: et ware scho registrĂ©iert Servicer dĂ©i mam WCF-Protokoll geschafft hunn. Si goufen an getrennten Versammlungen getrennt. Mir hunn se separat portĂ©iert, e klenge Launcher fir all Bau bĂ€igefĂŒĂŒgt. Et gouf geschriwwen mat der wonnerbarer Topshelf BibliothĂ©ik, dĂ©i Iech erlaabt d'Applikatioun souwuel als Service wĂ©i och als Konsol ze lafen. DĂ«st ass bequem fir Debugging well keng zousĂ€tzlech Projeten an der LĂ©isung erfuerderlech sinn.
D'Servicer goufen no der GeschÀftslogik verbonnen, well se gemeinsam Versammlungen benotzt hunn a mat enger gemeinsamer Datebank geschafft hunn. Si kéinte kaum Mikroservicer a senger reiner Form genannt ginn. Wéi och ëmmer, mir kënnen dës Servicer separat ubidden, a verschiddene Prozesser. Dëst eleng huet et méiglech hiren Afloss op all aner ze reduzéieren, reduzéieren de Problem mat parallel Entwécklung an engem eenzege Punkt vun Echec.
Assemblée mam Host ass just eng Zeil Code an der Programmklass. Mir hunn d'Aarbecht mat Topshelf an enger Hëllefsklass verstoppt.
namespace RBA.Services.Accounts.Host
{
internal class Program
{
private static void Main(string[] args)
{
HostRunner<Accounts>.Run("RBA.Services.Accounts.Host");
}
}
}
Déi zweet Manéier fir Mikroservicer ze verdeelen ass: schafen se fir nei Problemer ze léisen. Wann glÀichzÀiteg de Monolith net wÀchst, ass dëst schonn exzellent, dat heescht datt mir an déi richteg Richtung bewegen. Fir nei Problemer ze léisen, hu mir probéiert separat Servicer ze kreéieren. Wann et esou eng Geleeënheet war, hu mir méi "kanonesch" Servicer erstallt, déi hiren eegene Datemodell komplett verwalten, eng separat Datebank.
Mir, wéi vill, ugefaang mat Authentifikatioun an Autorisatioun Servicer. Si si perfekt fir dëst. Si sinn onofhÀngeg, als Regel, si hunn eng separat Datemodell. Si selwer interagéieren net mam Monolith, nëmmen et dréit sech un hinnen fir e puer Probleemer ze léisen. Mat dëse Servicer kënnt Dir den Iwwergank zu enger neier Architektur ufÀnken, d'Infrastruktur op hinnen debuggen, probéieren e puer Approche am Zesummenhang mat Netzwierkbibliothéiken, etc. Mir hu keng Teams an eiser Organisatioun déi keen Authentifikatiounsservice erstellen konnten.
Déi drëtt Manéier fir Mikroservicer ze verdeelenDee mir benotzen ass e bësse spezifesch fir eis. Dëst ass d'Entfernung vu GeschÀftslogik aus der UI Schicht. Eis Haapt UI Applikatioun ass Desktop; et ass, wéi de Backend, an C # geschriwwen. D'Entwéckler hunn periodesch Feeler gemaach an Deeler vun der Logik op d'UI transferéiert, déi am Backend sollt existéieren a weiderbenotzt ginn.
Wann Dir e richtegt Beispill aus dem Code vum UI Deel kuckt, kënnt Dir gesinn datt déi meescht vun dëser Léisung richteg GeschÀftslogik enthÀlt déi nëtzlech ass an anere Prozesser, net nëmme fir d'UI Form ze bauen.

Déi richteg UI Logik ass nëmmen do an de leschte puer Zeilen. Mir hunn et op de Server transferéiert fir datt et erëmbenotzt ka ginn, doduerch d'UI reduzéiert an déi richteg Architektur erreechen.
De véierten a wichtegste Wee fir Mikroservicer ze isoléieren, wat et méiglech mécht de Monolith ze reduzéieren, ass d'Entfernung vun existente Servicer mat der Veraarbechtung. Wa mir existéierend Moduler eraushuelen wéi et ass, ass d'Resultat net ëmmer dem Entwéckler gÀr, an de GeschÀftsprozess ka verÀnnert ginn zënter der Funktionalitéit erstallt gouf. Mat Refactoring kënne mir en neie GeschÀftsprozess ënnerstëtzen, well d'GeschÀftsfuerderunge konstant Ànneren. Mir kënnen de Quellcode verbesseren, bekannte MÀngel ewechhuelen an e besseren Datemodell erstellen. Et gi vill Virdeeler déi opkommen.
D'Trennung vu Servicer vun der Veraarbechtung ass onloschterlech mam Konzept vum begrenzte Kontext verbonnen. Dëst ass e Konzept vum Domain Driven Design. Et heescht eng Sektioun vum Domainmodell an deem all d'Begrëffer vun enger eenzeger Sprooch eenzegaarteg definéiert sinn. Kucke mer als Beispill de Kontext vun der Assurance an de Rechnungen. Mir hunn eng monolithic Applikatioun, a mir mussen mat de Kont an Versécherung schaffen. Mir erwaarden datt den Entwéckler eng existent Kont Klass an enger anerer Versammlung fënnt, et aus der Versécherungsklass referéiert, a mir hunn Aarbechtscode. Den DRY Prinzip gëtt respektéiert, d'Aufgab gëtt méi séier gemaach andeems Dir existente Code benotzt.
Als Resultat, stellt sech eraus, datt de Kontext vun Konten an Assurance verbonne sinn. Wéi nei Ufuerderunge entstinn, wÀert dës Kupplung d'Entwécklung stéieren, d'Komplexitéit vun der scho komplexer GeschÀftslogik erhéijen. Fir dëse Problem ze léisen, musst Dir d'Grenzen tëscht Kontexter am Code fannen an hir Violatioune lÀschen. Zum Beispill, am Versécherungskontext ass et ganz méiglech datt eng 20-Zifferen Zentralbankkontonummer an den Datum wou de Kont opgemaach gouf, genuch sinn.
Fir dës begrenzte Kontexter vuneneen ze trennen an de Prozess unzefÀnken fir Mikroservicer vun enger monolithescher Léisung ze trennen, hu mir eng Approche benotzt wéi extern APIen an der Applikatioun erstellen. Wa mir woussten datt e Modul e Mikrodéngscht sollt ginn, iergendwéi am Prozess geÀnnert, dann hu mir direkt Uruff un d'Logik gemaach, déi zu engem anere limitéierten Kontext gehéiert duerch extern Uruff. Zum Beispill, iwwer REST oder WCF.
Mir hunn fest decidéiert datt mir kee Code vermeiden deen verdeelt Transaktiounen erfuerdert. An eisem Fall war et ganz einfach dës Regel ze verfollegen. Mir hunn nach net Situatiounen begéint wou strikt verdeelt Transaktioune wierklech gebraucht ginn - déi lescht Konsistenz tëscht Moduler ass ganz genuch.
Loosst eis e spezifescht Beispill kucken. Mir hunn d'Konzept vun engem Orchester - eng Pipeline déi d'Entitéit vun der "Applikatioun" veraarbecht. Hien schaaft e Client, e Kont an eng Bankkaart am Tour. Wann de Client an de Kont erfollegrÀich erstallt ginn, awer d'Kaart Kreatioun feelt, geet d'Applikatioun net op de Status "erfollegrÀich" a bleift am Status "Kaart net erstallt". An Zukunft wÀert d'Hannergrond Aktivitéit et ophuelen a fÀerdeg maachen. De System ass zënter enger ZÀit an engem Zoustand vun Inkonsistenz, mÀ mir sinn allgemeng zefridde mat dësem.
Wann eng Situatioun entsteet wann et néideg ass en Deel vun den Donnéeën konsequent ze spÀicheren, wÀerte mir héchstwahrscheinlech fir d'Konsolidéierung vum Service goen fir se an engem Prozess ze veraarbecht.
Loosst eis e Beispill kucken fir e Mikroservice ze verdeelen. Wéi kënnt Dir et relativ sécher an d'Produktioun bréngen? An dësem Beispill hu mir e separaten Deel vum System - e Paieziedel Service Modul, ee vun de Code Rubriken vun deem mir gÀren microservice ze maachen.

Als éischt erstelle mir e Mikroservice andeems Dir de Code nei schreift. Mir verbesseren e puer Aspekter mat deenen mir net zefridden waren. Mir implementéieren nei GeschÀftsfuerderunge vum Client. Mir addéieren en API Gateway fir d'Verbindung tëscht der UI an dem Backend, deen Uruff Forwarding gëtt.

Als nÀchst verëffentleche mir dës Konfiguratioun an Operatioun, awer an engem Pilotstaat. Déi meescht vun eise Benotzer schaffen nach ëmmer mat alen GeschÀftsprozesser. Fir nei Benotzer entwéckelen mir eng nei Versioun vun der monolithescher Applikatioun déi dëse Prozess net méi enthÀlt. Wesentlech hu mir eng Kombinatioun vun engem Monolith an engem Mikroservice deen als Pilot funktionnéiert.

Mat engem erfollegrÀiche Pilot verstinn mir datt déi nei Konfiguratioun wierklech funktionnéiert ass, mir kënnen den alen Monolith aus der Equatioun ewechhuelen an déi nei Konfiguratioun an der Plaz vun der aler Léisung verloossen.

Am Ganzen benotze mir bal all existent Methoden fir de Quellcode vun engem Monolith opzedeelen. All vun hinnen erlaaben eis d'Gréisst vun Deeler vun der Applikatioun ze reduzéieren an se an nei Bibliothéiken ze iwwersetzen, fir bessere Quellcode ze maachen.
Schafft mat der Datebank
D'Datebank kann méi schlëmm wéi de Quellcode opgedeelt ginn, well se net nëmmen dat aktuellt Schema enthÀlt, awer och akkumuléiert historesch Daten.
Eis Datebank, wéi vill anerer, hat eng aner wichteg Nodeel - seng grouss Gréisst. Dës Datebank gouf no der komplizéierter GeschÀftslogik vun engem Monolith entworf, a Relatiounen cumuléiert tëscht den Dëscher vu verschiddene begrenzte Kontexter.
An eisem Fall, fir all d'Problemer (grouss Datebank, vill Verbindungen, heiansdo onkloer Grenzen tëscht Dëscher) opzemaachen, ass e Problem entstanen, deen a ville grousse Projete geschitt: d'Benotzung vun der gemeinsamer Datebank Schabloun. Daten goufen aus Dëscher duerch Vue, duerch Replikatioun geholl, an an aner Systemer geschéckt wou dës Replikatioun gebraucht gouf. Als Resultat konnte mir d'Dëscher net an e separat Schema réckelen, well se aktiv benotzt goufen.
Déiselwecht Divisioun a limitéierte Kontexter am Code hëlleft eis bei der Trennung. Et gëtt eis normalerweis eng zimlech gutt Iddi wéi mir d'Donnéeën um Datebankniveau ofbriechen. Mir verstinn wéi eng Dëscher zu engem begrenzte Kontext gehéieren a wéi eng zu engem aneren.
Mir hunn zwou global Methode vun der Datebankpartitionéierung benotzt: Partitionéierung vun existente Dëscher a Partitionéierung mat Veraarbechtung.
D'Ofdeelung vun existente Dëscher ass eng gutt Method fir ze benotzen wann d'Datestruktur gutt ass, GeschÀftsbedéngungen entsprécht, a jidderee mat deem zefridden ass. An dësem Fall kënne mir existéierend Dëscher an e separat Schema trennen.
En Departement mat Veraarbechtung ass gebraucht wann de GeschÀftsmodell sech staark verÀnnert huet, an d'Dëscher eis guer net méi zefridden stellen.
Splitting bestehend Dëscher. Mir mussen bestëmmen wat mir trennen. Ouni dëst Wëssen wÀert nÀischt funktionnéieren, an hei hëlleft d'Trennung vu begrenzte Kontexter am Code eis. Als Regel, wann Dir d'Grenze vu Kontexter am Quellcode versteet, gëtt et kloer wéi eng Tabellen an der Lëscht fir den Departement abegraff sinn.
Loosst eis virstellen datt mir eng Léisung hunn an dÀr zwee Monolith Moduler mat enger Datebank interagéieren. Mir mussen sécherstellen datt nëmmen ee Modul mat der Sektioun vun getrennten Dëscher interagéiert, an deen aneren fÀnkt mat der API ze interagéieren. Fir unzefÀnken ass et genuch datt nëmmen d'Opname duerch d'API duerchgefouert gëtt. Dëst ass eng noutwendeg Bedingung fir eis iwwer d'OnofhÀngegkeet vu Mikroservicer ze schwÀtzen. Liesverbindunge kënne bleiwen soulaang et kee grousse Problem ass.

De nÀchste Schrëtt ass datt mir d'Sektioun vum Code trennen, déi mat getrennten Dëscher funktionnéiert, mat oder ouni Veraarbechtung, an e getrennten Mikroservice an et an engem getrennten Prozess, e Container lafen. Dëst wÀert e separaten Service sinn mat enger Verbindung mat der Monolith-Datebank an déi Dëscher déi net direkt dozou bezéien. De Monolith interagéiert nach ëmmer fir ze liesen mam eraushuelbare Deel.

Spéider wÀerte mir dës Verbindung ewechhuelen, dat heescht, d'Liesen vun Daten aus enger monolithescher Applikatioun aus getrennten Dëscher gëtt och op d'API transferéiert.

Als nÀchst wÀerte mir aus der allgemenger Datebank d'Tabellen auswielen, mat deenen nëmmen den neie Mikroservice funktionnéiert. Mir kënnen d'Dëscher op e getrennten Schema réckelen oder souguer op eng separat kierperlech Datebank. Et gëtt nach ëmmer eng Liesverbindung tëscht dem Mikroservice an der Monolithdatenbank, awer et gëtt nÀischt ze Suergen, an dëser Konfiguratioun kann et zimmlech laang liewen.

De leschte Schrëtt ass all Verbindungen komplett ze lÀschen. An dësem Fall musse mir eventuell Daten aus der Haaptdatenbank migréieren. Heiansdo wëlle mir e puer Donnéeën oder Verzeichnisser replizéiert vun externe Systemer a verschiddenen Datenbanken weiderbenotzen. Dat geschitt eis periodesch.

Veraarbechtung Departement. Dës Method ass ganz Àhnlech wéi déi éischt, nëmmen an ëmgedréint Uerdnung. Mir verdeelen direkt eng nei Datebank an en neie Mikroservice, deen mam Monolith iwwer eng API interagéiert. Awer glÀichzÀiteg bleift et eng Rei vun Datebank Dëscher déi mir an Zukunft wëllen lÀschen. Mir brauchen et net méi, mir hunn et am neie Modell ersat.

Fir datt dëse Schema funktionnéiert, brauche mir méiglecherweis eng Iwwergangsperiod.
Et ginn dann zwou méiglech Approche.
Déi éischt: Mir duplizéieren all Daten an den neien an alen Datenbanken. An dësem Fall hu mir Datenredundanz a Synchroniséierungsproblemer kënnen entstoen. Mee mir kënnen zwee verschidde Clienten huelen. Een wÀert mat der neier Versioun schaffen, déi aner mat der aler.
Déi zweet: mir deelen d'Donnéeën no e puer GeschÀftskriterien. Zum Beispill hu mir 5 Produkter am System, déi an der aler Datebank gespÀichert goufen. Mir setzen de sechsten an der neier GeschÀftstask an enger neier Datebank. Awer mir brauche en API Gateway deen dës Donnéeën synchroniséiert an de Client weist wou a wat fir ze kommen.
Béid Approche funktionnéieren, wielt ofhÀngeg vun der Situatioun.
Nodeems mir sécher sinn, datt alles funktionnéiert, kann den Deel vum Monolith, deen mat alen Datebankstrukturen funktionnéiert, ausgeschalt ginn.

De leschte Schrëtt ass déi al Datestrukturen ze lÀschen.

Fir ze resuméieren, kënne mir soen datt mir Probleemer mat der Datebank hunn: et ass schwéier mat deem ze schaffen am Verglach zum Quellcode, et ass méi schwéier ze deelen, awer et kann a soll gemaach ginn. Mir hunn e puer Weeër fonnt, déi eis erlaben dëst ganz sécher ze maachen, awer et ass ëmmer méi einfach Feeler mat Daten ze maachen wéi mat Quellcode.
Schafft mat Quellcode
Dëst ass wéi d'Quellcode Diagramm ausgesinn wéi mir ugefaang de monolithesche Projet ze analyséieren.

Et kann ongeféier an drÀi Schichten opgedeelt ginn. Dëst ass eng Schicht vu lancéierte Moduler, Plugins, Servicer an eenzel Aktivitéiten. TatsÀchlech waren dës Entréen an enger monolithescher Léisung. All vun hinnen goufen enk mat enger gemeinsamer Schicht versiegelt. Et hat eng GeschÀftslogik déi d'Servicer gedeelt hunn a vill Verbindungen. All Service a Plugin benotzt bis zu 10 oder méi gemeinsam Versammlungen, ofhÀngeg vun hirer Gréisst an dem Gewësse vun den Entwéckler.
Mir haten d'Gléck fir Infrastrukturbibliothéiken ze hunn déi separat benotzt kënne ginn.
Heiansdo ass eng Situatioun entstanen, wann e puer gemeinsam Objeten eigentlech net zu dëser Schicht gehéieren, mee Infrastrukturbibliothéike waren. Dëst gouf geléist andeems se ëmbenennen.
Déi gréisste Suerg war begrenzte Kontexter. Et ass geschitt datt 3-4 Kontexter an enger gemeinsamer Versammlung gemëscht goufen a sech an deene selwechte GeschÀftsfunktiounen benotzt hunn. Et war néideg ze verstoen wou dëst ënnerdeelt ginn a laanscht wat Grenzen, a wat nÀchst ze maachen mat Kartéierung dëser Divisioun an Quellcode Assemblée.
Mir hunn e puer Reegele fir de Code Spaltprozess formuléiert.
Déi éischt: Mir wollten net méi GeschÀftslogik tëscht Servicer, Aktivitéiten a Plugins deelen. Mir wollten d'GeschÀftslogik onofhÀngeg bannent Mikroservicer maachen. Mikroservicer, op der anerer SÀit, sinn am Idealfall geduecht als Servicer déi komplett onofhÀngeg existéieren. Ech gleewen, datt dës Approche e bësse verschwendend ass, an et ass schwéier z'erreechen, well zum Beispill Servicer an C # wÀerten op alle Fall vun enger Standardbibliothéik verbonne sinn. Eise System ass an C # geschriwwe ginn; mir hunn nach keng aner Technologien benotzt. Dofir hu mir décidéiert datt mir eis leeschte kënnen gemeinsam technesch Versammlungen ze benotzen. Den Haapt Saach ass datt se keng Fragmenter vun der GeschÀftslogik enthalen. Wann Dir e Komfort-Wrapper iwwer den ORM hutt, deen Dir benotzt, da kopéiert se vum Service zum Service ganz deier.
Eist Team ass e Fan vum Domain-gedriwwenen Design, sou datt d'Zwiebelarchitektur gutt fir eis passt. D'Basis vun eise Servicer ass net d'Datenaccess Layer, mee eng Versammlung mat Domain Logik, déi nëmmen GeschÀftslogik enthÀlt a keng Verbindunge mat der Infrastruktur huet. Zur selwechter ZÀit kënne mir d'Domainversammlung onofhÀngeg Ànneren fir Probleemer am Zesummenhang mat Kaderen ze léisen.
Op dëser Etapp hu mir eisen éischte sérieux Problem begéint. De Service huet missen op eng Domainversammlung bezéien, mir wollten d'Logik onofhÀngeg maachen, an den DRY-Prinzip huet eis hei staark behënnert. D'Entwéckler wollte Klassen aus Nopeschversammlungen nei benotzen fir Duplikatioun ze vermeiden, an als Resultat hunn d'DomÀnen erëm matenee verbonnen. Mir hunn d'Resultater analyséiert an decidéiert datt vlÀicht de Problem och am BerÀich vum Quellcode-SpÀicherapparat lÀit. Mir haten e grousse Repository mat all de Quellcode. D'Léisung fir de ganze Projet war ganz schwéier op enger lokaler Maschinn ze montéieren. Dofir goufen separat kleng Léisunge fir Deeler vum Projet erstallt, a keen huet verbueden eng gemeinsam oder Domainversammlung derbÀi ze addéieren an se ze benotzen. Dat eenzegt Tool dat eis net erlaabt huet dëst ze maachen war Code review. Mee heiansdo huet et och gescheitert.
Duerno hu mir ugefaang op e Modell mat getrennten Repositories ze plĂ«nneren. D'GeschĂ€ftslogik flĂ©isst net mĂ©i vu Service zum Service, DomĂ€nen si wierklech onofhĂ€ngeg ginn. Begrenzte Kontexter ginn mĂ©i kloer Ă«nnerstĂ«tzt. WĂ©i benotze mir InfrastrukturbibliothĂ©ike weider? Mir hunn se an e getrennten Repository getrennt, hunn se dann an Nuget Packagen gesat, dĂ©i mir an Artifactory gesat hunn. Mat all Ănnerung geschitt d'Versammlung an d'Publikatioun automatesch.

Eis Servicer hunn ugefaang intern Infrastruktur Packagen op déiselwecht Manéier ze referenzéieren wéi extern. Mir download extern Bibliothéiken aus Nuget. Fir mat Artifactory ze schaffen, wou mir dës Packagen plazéiert hunn, hu mir zwee Packagemanager benotzt. A klenge Repositories hu mir och Nuget benotzt. A Repositories mat multiple Servicer hu mir Paket benotzt, wat méi Versiounskonsistenz tëscht Moduler ubitt.

Also, andeems mir um Quellcode schaffen, d'Architektur liicht Ànneren an d'Repositories trennen, maache mir eis Servicer méi onofhÀngeg.
Infrastrukturproblemer
Déi meescht vun den Nodeeler fir op Mikroservicer ze plënneren sinn Infrastruktur verbonnen. Dir braucht automatiséiert Deployment, Dir braucht nei Bibliothéike fir d'Infrastruktur ze bedreiwen.
Manuell Installatioun an Ămfeld
Am Ufank hu mir d'LĂ©isung fir Ămfeld manuell installĂ©iert. Fir dĂ«se Prozess ze automatisĂ©ieren, hu mir eng CI / CD Pipeline erstallt. Mir hunn de kontinuĂ©ierleche Liwwerprozess gewielt well kontinuĂ©ierlech Deployment nach net akzeptabel ass fir eis aus der Siicht vu GeschĂ€ftsprozesser. Dofir gĂ«tt d'SchĂ©cken fir d'Operatioun mat engem KnĂ€ppchen duerchgefouert, a fir ze testen - automatesch.

Mir benotzen Atlassian, Bitbucket fir Quellcode SpÀicheren a Bambus fir ze bauen. Mir schreiwen gÀr Build Scripten am Cake well et d'selwecht ass wéi C #. FÀerdeg Pakete kommen op Artifactory, an Ansible kënnt automatesch op d'Testserver, duerno kënnen se direkt getest ginn.

Separat Logged
Eng KĂ©ier war eng vun den Iddie vum Monolith fir gemeinsame Logbicher ze bidden. Mir mussen och verstoen wat mir maache mat den eenzelne Logbicher dĂ©i op den Disken sinn. Eis Logbicher ginn op Textdateien geschriwwe. Mir hunn decidĂ©iert e Standard ELK Stack ze benotzen. Mir hunn d'ELK net direkt duerch d'Provider geschriwwen, awer decidĂ©iert datt mir d'Textprotokoller finalisĂ©ieren an d'Spuer-ID an hinnen als IdentifizĂ©ierer schreiwen, de Servicenumm bĂ€igefĂŒĂŒgt, sou datt dĂ«s Logbicher spĂ©ider kĂ«nne parsĂ©iert ginn.

Mat Filebeat kënne mir eis Logbicher sammelen vun Serveren, transforméiert se dann, benotzt Kibana fir Ufroen an der UI ze erstellen, a kuckt wéi den Uruff tëscht de Servicer geroutet gouf. Trace IDs si ganz hëllefrÀich dofir.
Testen an Debugging verbonne Servicer
Am Ufank hu mir net ganz verstan wéi d'Servicer ze debuggen déi entwéckelt ginn. Alles war einfach mam Monolith; Mir hunn et op enger lokaler Maschinn gelaf. Am Ufank hu se probéiert datselwecht mat Mikroservicer ze maachen, awer heiansdo fir e Mikroservice komplett ze starten, musst Dir e puer anerer starten, an dëst ass onbequem. Mir hu gemierkt datt mir op e Modell musse plënneren, wou mir op der lokaler Maschinn nëmmen de Service oder Servicer verloossen, déi mir wëllen Debuggen. Déi reschtlech Servicer gi vu Servere benotzt déi mat der Konfiguratioun mat Prod passen. Nom Debugging, wÀhrend dem Test, fir all Aufgab, ginn nëmmen déi geÀnnert Servicer op den Testserver ausgestallt. Also gëtt d'Léisung an der Form getest an dÀr se an der Zukunft an der Produktioun erscheint.
Et gi Serveren déi nëmme Produktiounsversioune vu Servicer lafen. Dës Servere sinn am Fall vun TëschefÀll gebraucht, fir d'Liwwerung virum Asaz ze kontrolléieren a fir intern Training.
Mir hunn en automatisĂ©ierten Testprozess mat der populĂ€rer Specflow BibliothĂ©ik bĂ€igefĂŒĂŒgt. Tester lafen automatesch mat NUnit direkt nom Ofbau vun Ansible. Wann d'Taskofdeckung voll automatesch ass, da gĂ«tt et kee Besoin fir manuell Tester. Och wann heiansdo zousĂ€tzlech manuell Tester nach Ă«mmer erfuerderlech sinn. Mir benotzen Tags am Jira fir ze bestĂ«mmen wĂ©i eng Tester fir e spezifescht Thema lafen.
ZousÀtzlech ass de Besoin fir Laaschtestung eropgaang, virdrun gouf et nëmmen a rare FÀll duerchgefouert. Mir benotzen JMeter fir Tester auszeféieren, InfluxDB fir se ze spÀicheren, a Grafana fir Prozessgrafiken ze bauen.
Wat hu mir erreecht?
Als éischt hu mir d'Konzept vun "Verëffentlechung" entlooss. Gone sinn déi zwee-Mount monstréis Verëffentlechungen, wann dëse Koloss an engem Produktiounsëmfeld ofgesat gouf, temporÀr d'GeschÀftsprozesser stéieren. Elo setzen mir Servicer am Duerchschnëtt all 1,5 Deeg aus, gruppéiere se well se no der Genehmegung a Betrib ginn.
Et gi keng fatale Feeler an eisem System. Wa mir e Mikroservice mat engem Feeler verëffentlechen, da gëtt d'Funktionalitéit verbonne mat deem gebrach, an all aner Funktionalitéit gëtt net beaflosst. Dëst verbessert immens d'Benotzererfarung.
Mir kënnen den Ofbaumuster kontrolléieren. Dir kënnt Gruppe vu Servicer separat aus dem Rescht vun der Léisung auswielen, wann néideg.
ZousÀtzlech hu mir de Problem mat enger grousser Schlaang vu Verbesserunge wesentlech reduzéiert. Mir hunn elo separat Produktteams déi onofhÀngeg mat e puer vun de Servicer schaffen. De Scrum Prozess ass scho gutt hei. E spezifescht Team kann e separaten Produktbesëtzer hunn, deen et Aufgaben zouginn.
Summary
- Mikroservicer si gutt gëeegent fir komplex Systemer ofzebauen. Am Prozess fÀnken mir un ze verstoen wat an eisem System ass, wéi eng limitéiert Kontexter et sinn, wou hir Grenze leien. Dëst erlaabt Iech Verbesserungen tëscht Moduler korrekt ze verdeelen an Code Duercherneen ze verhënneren.
- Mikroservicer bidden organisatoresch Virdeeler. Si ginn dacks nĂ«mmen als Architektur geschwat, awer all Architektur ass gebraucht fir GeschĂ€ftsbedĂŒrfnisser ze lĂ©isen, an net eleng. Dofir kĂ«nne mir soen datt Mikroservicer gutt gĂ«eegent sinn fir Probleemer a klenge Teams ze lĂ©isen, well Scrum elo ganz populĂ€r ass.
- Trennung ass en iterative Prozess. Dir kĂ«nnt eng Applikatioun net huelen an se einfach a Mikroservicer opdeelen. Dat resultĂ©ierend Produkt ass onwahrscheinlech funktionell. Wann Dir Mikroservicer widmen, ass et gutt fir dĂ©i existent Legacy Ă«mzeschreiwen, dat heescht, et a Code Ă«mzewandelen, dee mir gĂ€r hunn a besser entsprĂ©cht GeschĂ€ftsbedĂŒrfnisser a punkto FunktionalitĂ©it a Geschwindegkeet.
E klengen Opgepasst: D'KĂ€schte fir op Mikroservicer ze plĂ«nneren sinn zimlech bedeitend. Et huet laang gedauert fir den Infrastrukturproblem alleng ze lĂ©isen. Also wann Dir eng kleng Applikatioun hutt dĂ©i keng spezifesch SkalĂ©ierung erfuerdert, ausser Dir hutt eng grouss Zuel vu Clienten dĂ©i fir d'Opmierksamkeet an d'ZĂ€it vun Ărem Team konkurrĂ©iere, da sinn Mikroservicer vlĂ€icht net dat wat Dir haut braucht. Et ass zimlech deier. Wann Dir de Prozess mat Mikroservicer ufĂ€nkt, da wĂ€erten d'KĂ€schte ufanks mĂ©i hĂ©ich sinn wĂ©i wann Dir dee selwechte Projet mat der EntwĂ©cklung vun engem Monolith starten.
PS Eng méi emotional Geschicht (a wéi fir Iech perséinlech) - laut .
Hei ass déi komplett Versioun vum Bericht.
Source: will.com
