Es gibt ver­schie­de­ne Mög­lich­kei­ten, wie man Software aufbauen kann. Statt ein Projekt bei­spiels­wei­se als großes Ganzes zu rea­li­sie­ren, kann es sinnvoll sein, die Aufgabe zu verteilen und kleine Pakete zu schnüren – so­ge­nann­te Mi­cro­ser­vices. Der Begriff hat dabei nicht nur viel mit dem Aufbau einer Com­pu­ter­an­wen­dung zu tun, sondern spielt auch bei der Planung im Sinne des agilen Pro­jekt­ma­nage­ments eine große Rolle. Welche Vorteile hat die Mi­cro­ser­vice-Ar­chi­tek­tur, wie funk­tio­niert sie und wo setzt man die Technik bereits ein?

„Do one thing and do it well“: eine Mi­cro­ser­vice-De­fi­ni­ti­on

Es gibt keine klare Ab­gren­zung, wann man von einer Mi­cro­ser­vice-Ar­chi­tek­tur sprechen kann und wann nicht. Um die Be­griffs­ver­wir­rung noch zu un­ter­stüt­zen, geht es bei Mi­cro­ser­vices nicht aus­schließ­lich um eine Software-Technik, sondern in großem Maße auch um eine Ar­beits­wei­se von Ent­wick­lern: Wie lassen sich große Pro­gram­mie­rungs­pro­jek­te am besten rea­li­sie­ren? Als generelle Regel kann man sich merken, dass Projekte, die Mi­cro­ser­vices einsetzen, immer Ken Thompsons Unix-Phi­lo­so­phie folgen: „Do one thing and do it well“. Man soll sich also auf eine Aufgabe kon­zen­trie­ren, diese aber zur Per­fek­ti­on bringen. Die Aussage ist nicht nur ein Ratschlag für die Pro­gram­mier­ar­beit, sondern be­schreibt auch die Funk­ti­ons­wei­se von einzelnen Mi­cro­ser­vices.

Im Sinne der Pro­gramm­ent­wick­lung ver­stan­den, soll man kleine Teams bilden, die sich um einen einzelnen Dienst kümmern – rea­li­siert in einem Mi­cro­ser­vice. Im Sinne des Pro­jekt­ma­nage­ments geht es also um eine Fo­kus­sie­rung der Teams und um deren Un­ab­hän­gig­keit. Statt einer zentralen Ad­mi­nis­tra­ti­on ist jedes Team voll für sein End­pro­dukt ver­ant­wort­lich, und zwar im kom­plet­ten Ent­wick­lungs­zy­klus: von der Ent­ste­hung bis zur Aus­lie­fe­rung und der an­schlie­ßen­den Über­wa­chung. Diese Ar­beits­wei­se bringt viele Vorteile mit sich und im Ergebnis eine modulare Software-Ar­chi­tek­tur hervor.

Fakt

Die Kom­bi­na­ti­on von Ar­beits­wei­se und Produkt geht auf das Gesetz von Conway zurück: Der In­for­ma­ti­ker Melvin Conway hatte bereits 1967 be­ob­ach­tet, dass die Struk­tu­ren von Pro­gram­men und anderen Systemen immer den Struk­tu­ren der Gruppe ähneln, die mit der Ent­wick­lung betraut ist.

Eine Mi­cro­ser­vice-Ar­chi­tek­tur ist prin­zi­pi­ell eine Wei­ter­ent­wick­lung von ser­vice­ori­en­tier­ter Ar­chi­tek­tur (SOA): Auch bei diesem Ar­chi­tek­tur­mus­ter spielen kleine Services eine Rolle. Diese sind aber immer noch ein­ge­bet­tet in ein großes System und nicht so un­ab­hän­gig, wie man es von einer Mi­cro­ser­vice-Ar­chi­tek­tur erwartet. Genau wie es für letztere keine klare De­fi­ni­ti­on gibt, ist auch SOA ein eher schwam­mi­ger Begriff. Daher sind die Übergänge zwischen den beiden Mustern fließend.

Mi­cro­ser­vice-Ar­chi­tec­tu­re vs. Mo­no­li­thic Ar­chi­tec­tu­re

Tra­di­tio­nel­le Pro­gramm­ent­wick­lung funk­tio­niert nach dem Prinzip des Mo­no­li­then: Man rea­li­siert alle Aufgaben in einer großen Anwendung. Alle einzelnen Services greifen auf eine große Datenbank zu und werden über ein Nut­zer­inter­face aus­ge­ge­ben – alles rea­li­siert innerhalb der einen Anwendung. Der Ansatz von Mi­cro­ser­vices geht von Modulen aus: Jeder Mi­cro­ser­vice ist nur für die Er­le­di­gung einer einzelnen Aufgabe zuständig. So ver­schie­den das Ergebnis bei beiden Ansätzen ist, so un­ter­schied­lich sind auch die Ar­beits­pro­zes­se.

Während bei einer Mi­cro­ser­vice-Ar­chi­tek­tur ein Team sich nur um die Ent­wick­lung eines Mi­cro­ser­vices kümmert, ist die Team­bil­dung bei Mo­no­li­then anders or­ga­ni­siert. Teams or­ga­ni­sie­ren sich nach der Tech­no­lo­gie, mit der sie sich aus­ein­an­der­set­zen: Ein Team befasst sich mit Da­ten­ban­ken, ein anderes pro­gram­miert die einzelnen Services und ein drittes befasst sich mit der Ge­stal­tung eines User-In­ter­faces. Für die Ver­öf­fent­li­chung von Updates, War­tungs­ar­bei­ten und Analysen sind wiederum andere Ar­beits­grup­pen zuständig. Al­ler­dings sind bei einem Mo­no­li­then alle Teams von­ein­an­der abhängig. In einer Mi­cro­ser­vice-Ar­chi­tek­tur sollen Ab­hän­gig­kei­ten so gut es geht vermieden werden.

Was sind die Vorteile einer Mi­cro­ser­vice-Ar­chi­tek­tur?

Bei einer Mi­cro­ser­vice-Ar­chi­tek­tur wird eine große Anwendung in Form von kleinen, mo­no­funk­tio­na­len Modulen (den Mi­cro­ser­vices) rea­li­siert. Die Bausteine selbst werden un­ab­hän­gig von­ein­an­der ent­wi­ckelt und bilden zusammen das Ge­samt­pro­dukt. Dieser Ar­chi­tek­tur­stil hat einige Vorteile.

Un­ab­hän­gig­keit

Bei der Ent­wick­lung eines Mi­cro­ser­vices agieren Teams in der Regel voll­kom­men autonom. Weder gibt eine über­ge­ord­ne­te, au­to­ri­tä­re Instanz eine Vor­ge­hens­wei­se vor, noch müssen sich die einzelnen Pro­jekt­grup­pen un­ter­ein­an­der ständig ko­or­di­nie­ren. Im Mit­tel­punkt des Teams steht einzig die Auf­ga­ben­stel­lung, der Nutzen des Mi­cro­ser­vices. Der Vorteil bei dieser Ar­beits­wei­se: Das Ent­wick­lungs­team kann den Lö­sungs­weg ein­schla­gen, der am besten für den Mi­cro­ser­vice geeignet ist, und nicht den, den andere vor­ge­ge­ben haben. Das geht so weit, dass es möglich ist, für ver­schie­de­ne Mi­cro­ser­vices auch un­ter­schied­li­che Pro­gram­mier­spra­chen zu verwenden oder eigene Da­ten­ban­ken bzw. Da­ten­bank­ver­wal­tungs­sys­te­me ein­zu­set­zen. Dies ist möglich, da jeder Mi­cro­ser­vice seine eigene Lauf­zeit­um­ge­bung besitzt.

Ro­bust­heit

Ein weiterer Vorteil der Un­ab­hän­gig­keit ist, dass das komplette System dadurch sehr viel robuster wird. Sollte ein Mi­cro­ser­vice ausfallen, bricht nicht die komplette Anwendung zusammen, nur der Teil­aspekt funk­tio­niert nicht mehr. Da es sich hierbei um einen über­schau­ba­ren Prozess handelt, ist außerdem die Feh­ler­su­che sehr viel einfacher: Statt den Quellcode eines großen Mo­no­li­then zu durch­su­chen, braucht nur ein relativ kleines, in sich ge­schlos­se­nes Programm ana­ly­siert zu werden.

In diesem Zu­sam­men­hang lässt sich auch Con­ti­nuous Delivery nennen: Hierbei werden Software-Produkte ständig wei­ter­ent­wi­ckelt. Mi­cro­ser­vices geben Her­stel­lern die Mög­lich­keit, nicht in großen Etappen updaten zu müssen. Statt­des­sen werden Wei­ter­ent­wick­lun­gen eines Mi­cro­ser­vices direkt – natürlich nach einer ent­spre­chen­den Testphase – ver­öf­fent­licht, un­ab­hän­gig von den rest­li­chen Prozessen. Auch kleinere Än­de­run­gen in einem De­ploy­ment-Mo­no­li­then vor­zu­neh­men, kann sehr aufwendig sein. Einen Mi­cro­ser­vice, der ja nur eine einzige Aufgabe erfüllt, ab­zu­än­dern, ist viel einfacher zu be­werk­stel­li­gen, schließ­lich ver­braucht er viel weniger Res­sour­cen.

Der Con­ti­nuous Delivery kommt auch die agile Ar­beits­wei­se zugute: Das Team, dass sich um diesen Mi­cro­ser­vice kümmert, ist absoluter Spe­zia­list und kann Än­de­run­gen ohne große Probleme vornehmen. Darüber hinaus wird ohnehin nur eine Änderung im Quelltext (ein neues Feature oder ein Bugfix) pro Version vor­ge­nom­men. Dies hilft zu­sätz­lich dabei, zügige Än­de­run­gen vor­zu­neh­men und damit die Sta­bi­li­tät des Ge­samt­sys­tems lang­fris­tig zu sichern.

Kom­pa­ti­bi­li­tät

Am Ende fügt man alle Bausteine zusammen: So ver­schie­den die Mi­cro­ser­vices im Aufbau auch sind, am Ende müssen sie ge­mein­sa­me An­knüp­fungs­punk­te haben. Diese sollen möglichst einfach gestaltet sein, damit die Ver­bin­dung wenig Einfluss auf den ei­gent­li­chen Prozess nimmt. Deshalb setzen die meisten Ent­wick­ler von Mi­cro­ser­vices auf REST-APIs. Über die ein­heit­li­chen und schlanken HTTP-Methoden wie GET oder POST können die einzelnen Mi­cro­ser­vices einfach mit­ein­an­der kom­mu­ni­zie­ren und die ent­spre­chen­den In­for­ma­tio­nen aus­tau­schen.

Ska­lier­bar

Wenn ein Monolith (also ein ge­schlos­se­nes System, das alle Prozesse in sich vereint) nach oben skaliert werden muss, ist man gezwungen, das komplette System zu spiegeln. Eine Mi­cro­ser­vice-Ar­chi­tek­tur gibt Ent­wick­lern die Mög­lich­keit, sehr fein­gra­nu­lar zu skalieren. Man braucht nur den Service zu stärken, der dies benötigt. Das hält schließ­lich auch das End­pro­dukt sehr viel schlanker und spart Res­sour­cen. Ebenfalls ist es nicht so aufwendig, einen komplett neuen Service in das System zu in­te­grie­ren.

So werden Mi­cro­ser­vices-Ar­chi­tec­tures umgesetzt

Mi­cro­ser­vices sind un­ter­ein­an­der voll­kom­men isoliert und laufen in einer eigenen Umgebung. Nur über Schnitt­stel­len kom­mu­ni­zie­ren die einzelnen An­wen­dun­gen mit­ein­an­der. Um eine solche Isolation durch­zu­füh­ren, gibt es ver­schie­de­ne Mög­lich­kei­ten:

  • Container: Die viel­leicht häufigste Art, eine Mi­cro­ser­vice-Ar­chi­tek­tur auf­zu­bau­en, funk­tio­niert mit Con­tai­nern. Diese stellen eine sehr schlanke Form von Vir­tua­li­sie­rung dar, denn es werden nicht komplette virtuelle Maschinen erzeugt. Statt­des­sen baut man auf einem be­stehen­den Be­triebs­sys­tem auf und nutzt dessen Kernel. In den Con­tai­nern laufen die Mi­cro­ser­vices komplett autark: Alles was sie benötigen, um zu funk­tio­nie­ren, steckt mit im Container.

  • Virtuelle Maschinen: Es ist möglich, für jeden Mi­cro­ser­vice eine eigene virtuelle Maschine zu erzeugen. Auch hierbei können die Mi­cro­ser­vices isoliert von­ein­an­der agieren. Der Nachteil gegenüber einer Container-Tech­no­lo­gie wie Docker ist al­ler­dings, dass jede virtuelle Maschine ein eigenes Be­triebs­sys­tem benötigt und damit sehr viele Res­sour­cen.

Denkbar wäre sogar, für jeden Mi­cro­ser­vice eine eigene, physische Ser­ver­in­stanz auf­zu­set­zen. In der Praxis dürfte dies al­ler­dings einer großen Res­sour­cen­ver­schwen­dung gleich­kom­men, weshalb man in der Regel auf Vir­tua­li­sie­rung setzt. Ganz wichtig ist aber, egal für welche Rea­li­sie­rung man sich ent­schei­det, dass die Iso­lie­rung wirklich gegeben ist. Es ist weder anzuraten, mehrere Mi­cro­ser­vices auf einem Server laufen zu lassen, noch sie zusammen in einen Container zu stecken. Das könnte zu Kon­flik­ten zwischen den einzelnen An­wen­dun­gen führen. Damit es im gesamten System nicht zu Über­las­tun­gen kommt, setzt man Load Balancer ein. Diese verteilen die Last au­to­ma­tisch auf un­ter­schied­li­che Instanzen, um Ausfällen vor­zu­beu­gen.

Arbeiten mit Mi­cro­ser­vices: 3 Beispiele

In­zwi­schen haben Mi­cro­ser­vice-Ar­chi­tek­tu­ren Einzug in die Systeme von großen Un­ter­neh­men gehalten. Die Un­ter­neh­men haben es so geschafft, gewisse Probleme aus dem Weg zu schaffen oder ihre Abläufe zu op­ti­mie­ren. Die Beispiele von Netflix, Spotify und eBay zeigen, warum sich große Un­ter­neh­men mit eta­blier­ten mo­no­li­thi­schen Systemen ent­schei­den, die Ar­chi­tek­tur auf­zu­bre­chen und Mi­cro­ser­vices zu bilden. Auch andere IT-Firmen wie Google und Amazon arbeiten auf diese Art. Sie setzten modulare Systeme teilweise schon ein, als es dafür noch gar keinen Namen gab.

Netflix

Wie bei den meisten Un­ter­neh­men basierte der Service von Netflix früher (zu Zeiten, als Netflix noch kein On­line­strea­ming-Dienst war, sondern nur DVDs per Post ver­schick­te) auf einem mo­no­li­thi­schen System. Im Jahr 2008 gab es einen Fehler in einer Datenbank, der dazu führte, dass der komplette Dienst vier Tage lang ausfiel. Daraufhin entschied man sich, das alte System auf­zu­bre­chen und in Mi­cro­ser­vices auf­zu­tei­len. Damit erreichte man, dass das Un­ter­neh­men Än­de­run­gen sehr viel schneller live schalten konnte und so auch Re­pa­ra­tu­ren viel zügiger von­stat­ten­gin­gen. Da das System von Netflix enorm um­fang­reich ist, ent­wi­ckel­te man ein eigenes Programm, um die einzelnen Mi­cro­ser­vices un­ter­ein­an­der zu or­ga­ni­sie­ren: Conductor. Conductor gibt Netflix u. a. die Mög­lich­keit, Mi­cro­ser­vices zentral zu steuern (pausieren oder neu­star­ten) oder zu skalieren. Im Kern des Programms arbeitet ein Service namens Decider. Dieser kann au­to­ma­ti­siert Prozesse planen und so auf Er­eig­nis­se im Workflow reagieren. Weitere Programme, die Netflix ent­wi­ckelt hat, um effektiv mit Mi­cro­ser­vices arbeiten zu können, sind Mantis (Stream-pro­ces­sing), Dynomite (datastore) und Vizceral (traffic intuition).

Tipp

Netflix greift sehr häufig auf Open-Source-Programme zurück und stellt daher auch die eigenen Ent­wick­lun­gen offen ins Netz. In ihrem GitHub-Profil können alle genannten Programme ein­ge­se­hen werden.

Spotify

Ein weiterer Streaming-Dienst, Spotify, setzt bei seinem Angebot ebenfalls auf Mi­cro­ser­vices. Die Her­aus­for­de­rung, die Spotify in seinem Ent­wick­lungs­all­tag begegnen muss, ist die starke Kon­kur­renz. Der Au­dio­strea­ming-Markt hat mit Amazon, Apple und Google einige der größten IT-Un­ter­neh­men der Welt als Mit­spie­ler. Gleich­zei­tig müssen die Ent­wick­ler aufgrund stei­gen­der Nut­zer­zah­len ständig einen höheren Bedarf abdecken und bestimmte Ge­schäfts­re­geln (etwa Li­zenz­rech­te) beachten. Um schnell auf neue Ent­wick­lun­gen der Kon­kur­renz reagieren zu können und eigene In­no­va­tio­nen schneller zu ver­öf­fent­li­chen – damit wiederum die Kon­kur­renz reagieren muss –, sind Mi­cro­ser­vices die richtige Lösung für Spotify.

Bei­spiels­wei­se ist die Funktion, dass Nutzer bereits beim Eintippen eines Such­be­griffs Vor­schlä­ge erhalten, ein in sich ge­schlos­se­ner Mi­cro­ser­vice, um den sich ein eigenes Team kümmert. Zu­sätz­lich pro­fi­tiert Spotify von der Ro­bust­heit einer Mi­cro­ser­vice-Ar­chi­tek­tur: Wenn ein einzelner Mi­cro­ser­vice ausfällt, wird nicht das komplette Produkt un­brauch­bar. Insgesamt sind bei Spotify über 800 Mi­cro­ser­vices aktiv. Der Streaming-Dienst nutzt übrigens für einen Großteil der Mi­cro­ser­vices Java. Dies hat al­ler­dings nichts damit zu tun, dass Mi­cro­ser­vices nicht in un­ter­schied­li­chen Pro­gram­mier­spra­chen ge­schrie­ben werden können. Tat­säch­lich hat es mit den Ar­beits­pro­zes­sen zu tun: Ent­wick­ler wechseln ständig von einem Team ins andere – da ist es einfacher, wenn alle die gleiche Sprache verwenden.

7LGPeBgNFuU.jpg Zur Anzeige dieses Videos sind Cookies von Drittanbietern erforderlich. Ihre Cookie-Einstellungen können Sie hier aufrufen und ändern.

eBay

Die Ver­kaufs­platt­form eBay begann – wie die meisten Systeme – als Monolith: Zwi­schen­zeit­lich hatte eBay 3,4 Millionen Zeilen Code in nur einer einzigen Datei. Aus dieser Situation heraus entschied man sich, den Mo­no­li­then auf­zu­bre­chen und Mi­cro­ser­vices (in Java) zu ent­wi­ckeln. Auch bei eBay kom­mu­ni­zie­ren die einzelnen Services via REST mit­ein­an­der.

Die Tatsache, dass eBay und viele andere Un­ter­neh­men den Weg von einer mo­no­li­thi­schen zu einer Mi­cro­ser­vice-Ar­chi­tek­tur er­folg­reich gegangen sind, beweist den Nutzen der mo­der­ne­ren Her­an­ge­hens­wei­se. Während in den An­fangs­ta­gen eines On­line­pro­jekts mit wenigen aktiven Nutzern und einem über­schau­ba­ren Angebot ein Monolith voll­kom­men ausreicht, wird dieser mit stei­gen­den An­for­de­run­gen zum wachs­tums­hem­men­den Ungetüm.

Fazit: Ist Mi­cro­ser­vice-Ar­chi­tec­tu­re grund­sätz­lich besser?

Auch wenn vieles dafür spricht, Systeme auf Basis von Mi­cro­ser­vice-Ar­chi­tek­tu­ren auf­zu­bau­en, muss das moderne Vorgehen nicht für jedes Un­ter­neh­men bzw. jedes Projekt die richtige Lösung sein. Gerade für kleinere Com­pu­ter­pro­gram­me, die ohnehin nur wenige Aufgaben be­wäl­ti­gen, kann die Eta­blie­rung von Mi­cro­ser­vices einen erhöhten Aufwand bedeuten. Nicht nur die Er­stel­lung der Services, sondern auch Wartung, Wei­ter­ent­wick­lung und Mo­ni­to­ring sind ver­gleichs­wei­se aufwendig. Gerade auch bei der Über­wa­chung der Prozesse (Mo­ni­to­ring) muss ge­nau­es­tens abgewogen werden, ob diese mit Mi­cro­ser­vices besser oder schlech­ter gelingt: Auf der einen Seite sind einzelne Mi­cro­ser­vices sehr einfach zu ana­ly­sie­ren und zu messen. Durch die Masse an Mi­cro­ser­vices wächst diese Aufgabe aber enorm.

Schaut man sich die Vorteile der Ar­beits­ab­läu­fe an, wird er­sicht­lich, dass dies nicht für jedes Projekt – vor allem nicht kurz­fris­tig – sinnvoll ist. Ein Pluspunkt bei der Arbeit mit Mi­cro­ser­vices ist die Un­ab­hän­gig­keit der einzelnen Teams. Man möchte z. B. vermeiden, dass ein Team auf die Er­geb­nis­se eines anderen warten muss. Wenn das komplette Ent­wick­ler­team aber ohnehin nur aus wenigen Personen besteht, hat diese Trennung wenig Sinn. Zudem wird – wenn man dem Gesetz von Conway folgt – ein kleines Team, in dem man aus prag­ma­ti­schen Gründen keine klaren Trenn­li­ni­en ziehen kann und vieles in Per­so­nal­uni­on erledigt, ohnehin ein anderes Ergebnis erzielen.

Und auch bei größeren Teams ist eine um­fang­rei­che Um­stel­lung nötig: Po­si­tio­nen, die die Ent­wick­lung zentral steuern, fallen vermehrt weg, statt­des­sen or­ga­ni­sie­ren sich Ent­wick­ler­teams selbst. Eine solche Um­struk­tu­rie­rung ist sowohl zeit- als auch kos­ten­in­ten­siv. Auch dies darf man bei einer even­tu­el­len Um­stel­lung des Systems nicht außer Acht lassen.

Einige Be­für­wor­ter von Mi­cro­ser­vice-Ar­chi­tek­tu­ren empfehlen daher eine Monolith-first-Strategie. Demnach ist es sinnvoll, ein Pro­gram­mier­pro­jekt zunächst als Mo­no­li­then anzugehen und die Vorteile dieser Her­an­ge­hens­wei­se vor allem in den An­fangs­ta­gen aus­zu­schöp­fen. Erst wenn das Projekt einen ent­spre­chen­den Umfang an­ge­nom­men hat, sollte man auf eine Mi­cro­ser­vice-Ar­chi­tek­tur umsteigen. Zwischen beiden Systemen findet man die ser­vice­ori­en­tier­te Ar­chi­tek­tur (SOA), die als guter Zwi­schen­schritt geeignet ist. Auch hierbei wird mo­du­la­ri­siert vor­ge­gan­gen. Die einzelnen Dienste sollen dabei Ge­schäfts­pro­zes­se abbilden.

Zum Hauptmenü