Tod durch tausend Microservices
(renegadeotter.com)- Die Kritik lautet, dass eine Kultur, die Microservices wie eine Standardeinstellung einführt, Kosten und Komplexität erhöht hat, um Probleme zu lösen, die es gar nicht gibt, statt tatsächliche Skalierungsprobleme
- Die Abschottung des JavaScript-/Node.js-Ökosystems, Praktiken im FAANG-Stil und reichlich Venture Capital wirkten zusammen und schufen auch bei Startups eine Stimmung, in der man web-scale Architekturen nachahmte
- Auch mit Docker und Kubernetes verschwinden die Schwierigkeiten verteilter Systeme wie Entwicklung, Debugging, Deployment, Tests und Sicherstellung von Resilienz nicht
- Dropbox, Twitter, Netflix, Facebook, GitHub, Instagram, Shopify, StackOverflow, WhatsApp und andere starteten mit monolithischen Codebasen oder haben bis heute einen Monolithen im Kern
- Die meisten Unternehmen erreichen nie eine Größenordnung, in der sie wirklich verteilte Systeme brauchen; realistischer ist es daher, nur dann etwas als Service auszulagern, wenn es eine klar abgrenzbare und separat zu skalierende Last gibt
Eine Kultur, die Komplexität verehrt
- Die Satire, die daran scheitert, ein komplexes Microservice-Labyrinth zu erklären, nur um an das Geburtsdatum eines Nutzers zu kommen, zielt auf das Overengineering der heutigen Technikkultur
- Das Problem ist, dass sich das Ziel dahin verschoben hat, Geld dafür zu verbrennen, Probleme zu lösen, die es gar nicht gibt, statt die anstehenden Aufgaben zu erledigen
- Die Kritik an JavaScript und Node.js betrifft nicht nur eine bestimmte Technologie, sondern hängt mit der Gefahr abgeschotteter Software-Ökosysteme zusammen, in denen bereits gelernte Lektionen erneut gelernt werden müssen
- Die Branche ist auch früher schon gegen Komplexitätswände wie CORBA und SOAP gelaufen und hat danach den Kurs korrigiert
Bedingungen, die den Microservice-Hype ermöglichten
- Entwickler, die JavaScript für den Browser nutzten, bezeichneten sich als „full-stack“, gingen in Serverentwicklung und asynchronen Code hinein; frühes Node war eher ein persönliches Lernprojekt, und frühes JavaScript war für Serverentwicklung eine problematische Wahl
- Weil die Welt außerhalb von Node praktisch als nicht existent wahrgenommen wurde, entstand ein dogmatisches Denken, nach dem der Node-Weg der einzige Weg sei
- Später kamen ehemalige FAANG-Leute in Startups und verbreiteten „wie wir es bei Google gemacht haben“ unabhängig von Kontext und Größenordnung als die richtige Antwort
- Ein typisches Beispiel ist der Druck, dass es ohne separaten
User Preferences Servicenicht skalieren werde
- Ein typisches Beispiel ist der Druck, dass es ohne separaten
- In Zeiten reichlich vorhandenen Venture Capitals wurde es wichtiger, Investoren explosives Wachstum zu zeigen, als Umsatz zu erzielen; Unternehmen stellten schnell teure Software Engineers ein und ließen sie „irgendetwas“ tun
Verteilte Systeme bleiben schwierig
- Microservices wurden als „neue Art, skalierbare Software zu schreiben“ verpackt, berühren aber im Kern Probleme verteilter Systeme, die es schon lange gibt
- Früher galten verteilte Systeme als schwierige und riskante Werkzeuge, eher als letztes Mittel für besonders knifflige Probleme
- In verteilten Systemen werden alle folgenden Aufgaben schwieriger und dauern länger
- Entwicklung
- Debugging
- Deployment
- Tests
- Sicherstellung von Resilienz
- Für Microservice-basierte Entwicklung gibt es keine Standardwerkzeuge oder gemeinsamen Frameworks; auch in den 2020ern ist Arbeit an verteilten Systemen nur etwas einfacher geworden
- Docker und Kubernetes entfernen die wesentliche Komplexität verteilter Setups nicht auf magische Weise
Fälle, in denen Einfachheit bessere Ergebnisse brachte
- Eine Zusammenfassung von fünf Jahren Code-Audits bei Startups hält fest, dass besonders erfolgreiche Startups fast schon dreist einen Keep It Simple-Ansatz verfolgten
- Frühe Umstellungen auf Microservices, Architekturen, die auf Distributed Computing setzten, und Messaging-zentrierte Designs waren zentrale Fallen, die mehrere Unternehmen in Schwierigkeiten brachten
- Viele Startups bauen einfache und performante Systeme und empfinden dennoch falsche Minderwertigkeitsgefühle, weil sie „nicht vom ersten Tag an Microservices machen“
- Die Antwort auf die Frage „Wir haben nur einen Django-Monolithen und eine MySQL-Instanz, die von ein paar Engineers betreut werden – was ist daran falsch?“ lautet fast immer: „Nichts ist daran falsch“
- Auch erfahrene Engineers fühlen sich in der heutigen Technikkultur unzulänglich, doch das eigentliche Problem kann eine Umgebung aus ungerechtfertigtem Selbstvertrauen, Verschwendung und Dunning-Kruger sein
Unternehmen, die auch mit Monolithen gewachsen sind
- Die Vorstellung, ohne Monolithen könne man nicht wachsen, ist nahezu ein Mythos
- Dropbox, Twitter, Netflix, Facebook, GitHub, Instagram, Shopify, StackOverflow und andere begannen mit monolithischen Codebasen, und manche behalten bis heute einen Monolithen im Kern
- StackOverflow stellt auf seiner Performance-Seite stolz heraus, dass es eine große Website mit wenig Hardware betreibt
- Shopify nutzt weiterhin einen Rails-Monolithen und verarbeitet mit dem bewährten Resque Milliarden von Jobs
- WhatsApp wuchs mit einem Erlang-Monolithen und rund 50 Engineers enorm
- Die Engineering-Organisation wurde mit etwa 50 Personen klein gehalten
- Einzelne Teams sind 1 bis 3 Personen groß und haben hohe Autonomie
- Man bevorzugt wenige Server und skaliert jeden Server so weit wie möglich vertikal
- Instagram wurde mit einem Team von 12 Personen für Milliarden übernommen, und auch Threads folgt dem Instagram-Modell
Man sollte keine Probleme lösen, die es nicht gibt
- Die Kernfrage lautet: „Welches Problem wird gelöst?“
- Wenn Skalierung das Problem ist, braucht man Daten, die zeigen, was warum als separater Service aufgeteilt werden muss
- Verteilte Systeme werden für Skalierung und Resilienz gebaut, doch man muss auch Szenarien berücksichtigen, in denen ein Service langsam wird oder ausfällt und Traffic auf andere Services ausweicht
- Die nötigen Überlegungen hängen von Nutzungsmustern und Lastcharakteristik des Systems ab
- Backpressure
- Circuit Breaker
- Queues
- Jitter
- sinnvolle Timeouts für alle Endpunkte
- Schutzmechanismen, damit kleine Änderungen keinen Gesamtausfall verursachen
- Die meisten Unternehmen erreichen nicht die enorme Größenordnung, in der sie wirklich verteilte Systeme brauchen
- Wer die Arbeitsweise von Amazon und Google nachahmt, ohne deren Größenordnung, Expertise und Ressourcen zu haben, verschwendet leicht Zeit und Geld
- Es bleibt die Warnung: Ein schlechtes verteiltes System ist schwieriger als ein verteiltes System an sich
Das Ideal und die Realität von Services und APIs pro Team
- Der Versuch, die verteilte Topologie an die Unternehmensstruktur anzupassen, geht von der Idee aus, dass Probleme einfacher werden, wenn man sie in kleine Teile zerlegt
- Der ideale Microservice wird von einem dedizierten Team strikt gepflegt, versteckt sich hinter einer schönen, abwärtskompatiblen versionierten API und erfordert kaum Kommunikation mit anderen Teams
- In der Realität quellen Slack-Kanäle mit Releases, Bugs, Konfigurationsänderungen, Breaking Changes und Ankündigungen über
- Alle müssen ständig über alles im Bilde sein, und ohnehin beschäftigte Teams betreuen häufig mehrere Microservices halbherzig
- Mit Personalwechseln ändert sich auch die Service-Ownership, und statt eines guten Rennwagens entstehen mehrere miserable Golfcarts
Was Microservices kosten
-
Schwächung von DRY
- Microservices sind grundsätzlich nicht DRY, und jeder Service enthält duplizierten Boilerplate-Code
- Bei kleinen Microservices kann der Anteil an Plumbing-Code so groß werden, dass die durchschnittliche Service-Instanz eher aus „Service“-Code als aus Produktcode besteht
- Auch der Versuch, gemeinsamen Code auszulagern, bringt nur schmerzhafte Optionen mit sich
- Erstellt man eine gemeinsame Library, muss man Versions- und Update-Strategien festlegen
- Man kann regelmäßig Pull Requests in alle Repositories stellen, um Updates zu erzwingen
- Fasst man alles in einem Monorepo zusammen, entstehen dessen eigene Probleme
- Man akzeptiert etwas Code-Duplizierung oder lässt jedes Team jedes Mal das Rad neu erfinden
-
Verschlechterung der Developer Experience
- Developer Experience ist das Maß an Reibung und Aufwand, das für die Entwicklung neuer Features oder das Beheben von Bugs nötig ist
- In einer Microservice-Umgebung braucht man eine mentale Karte des gesamten Systems, um zu wissen, welche Services man für eine bestimmte Aufgabe starten muss und welches Team bzw. welche Person man was fragen sollte
- Spotify entwickelte Backstage, um die Vielzahl an Systemen und Services zu katalogisieren; das ist ein Hinweis darauf, wie teuer dieses Spiel ist
- Unternehmen, die nicht Spotify sind, bauen sich Ad-hoc-Lösungen, bei denen Robustheit und Portabilität kaum zu erwarten sind
- Um einen neuen Service zu starten, müssen viele Dinge automatisiert werden
- GitHub-/GitLab-Entwicklerrechte
- Standard-Umgebungsvariablen und Konfiguration
- CI/CD
- Prüfungen der Codequalität
- Code-Review-Einstellungen
- Branch-Regeln und Schutzmaßnahmen
- Monitoring und Observability
- Test Harness
- Infrastructure as Code
- Verwendet man mehrere Programmiersprachen, wächst diese Liste mit der Zahl der Sprachen
- Das Ausfeilen solcher Automatisierung kann Monate dauern, und man steht vor der Wahl, ob man Produkt oder Werkzeuge baut
-
Schwierigkeit von Integrationstests
- Selbst wenn Tests einzelner Services und Unit Tests bestehen, ist es eine andere Frage, ob die kritischen Pfade nach jedem Commit weiterhin funktionieren
- Integrationstests in einem verteilten Setup gelten als nahezu unmögliches Problem; an ihre Stelle ist Observability getreten
- Observability ist zu einem neuen Industriebereich geworden und kostet nicht nur Geld, sondern auch Entwicklerzeit
- Observability funktioniert nicht einfach wie ein Plug-in; man muss Canary Releases und Feature Flags verstehen und implementieren
- Das Zerlegen eines Problems macht die Lösung nicht einfacher, sondern liefert ein Bündel schwierigerer Probleme
Ein Monolith ist nicht automatisch guter Code
- Das Plädoyer für Monolithen bedeutet nicht: „Monolithen sind guter Code und Microservices schlechter Code“
- In der Realität gibt es viele mittelmäßige Monolithen, die von hastigen oder durchschnittlichen Teams gebaut wurden
- Verteilte Systeme sind jedoch wesentlich gnadenloser gegenüber Pfusch, schlechten Entscheidungen und übersehenen Failure Modes
- Wenn man nicht dauerhaft auf hohem Niveau arbeitet, zahlt man in verteilten Systemen den Preis
Vielleicht reichen Services statt Microservices
- Ein Service muss nicht unbedingt „micro“ sein; manchmal reichen einfach Services
- Manche Startups gingen so weit, für jede Funktion einen Service zu bauen, was zeigt, wie weit ungeprüfter Cargo Cult gehen kann
- Mit einem Monolithen zu beginnen ist eine klare Option
- Auch das „trunk & branches“-Muster kann in vielen Fällen passen
- Die Kernfunktionalität übernimmt der Hauptmonolith, also „Fleisch und Kartoffeln“
- Klar identifizierbare Lasten, die separat skaliert werden müssen, übernimmt ein Branch-Service
- Ein CPU-intensiver
Image-Resizing Serviceergibt als separater Service mehr Sinn als einUser Registration Service - Die Frage, ob die Zahl der Registrierungen pro Sekunde so hoch ist, dass unabhängige horizontale Skalierung nötig wird, dient als Kriterium für die Service-Abspaltung
Rückzug des Hypes und realistische Entscheidungen
- Die Überhitzung rund um Microservices scheint abzukühlen, und da der Fluss von Venture Capital knapper wird, sorgt der Markt dafür, dass Unternehmen vernünftigere Entscheidungen treffen
- Geld für web-scale Architekturen auszugeben, obwohl man keine web-scale Probleme hat, ist nicht nachhaltig
- Wenn man von New York nach Philadelphia muss, ist ein 90-minütiges Amtrak-Ticket die passendere Lösung für das Problem, als ein komplexes Raumschiff zu bauen
1 Kommentare
Meinungen auf Hacker News
Ich gehöre zu den Leuten, die Microservices stark befürwortet haben, habe beim Aufbau der Netflix-Plattform geholfen und bin um die Welt gereist, um ihre Vorteile zu predigen. Wenn ich Startups berate, sage ich aber fast immer, dass sie mit einem Monolithen anfangen sollen.
Es ist viel einfacher, Codebasis und Datenbank zusammenzuhalten, und das skaliert ziemlich lange. Wenn man einen Key/Value-Store wie DynamoDB verwendet, verliert man zwar einige relationale Funktionen, hält aber noch länger durch.
Auch einen Monolithen kann man auf Lambda deployen, und man kann die Vorteile von Lambda nutzen, ohne Services aufzuteilen.
Erst wenn man gewachsen ist, sollte man Teile, die unabhängig skalieren müssen oder separate Deployments brauchen, als Microservices mit eigenem Datenspeicher herauslösen.
Microservices verschlingen allein für die Pflege der Plattform mindestens 25 % der Engineering-Zeit; wenn man diese Effizienz nicht wieder hereinholen kann, sind sie es nicht wert.
Während man wächst – und eigentlich in den meisten Fällen – ist es besser, gar keine Microservices zu machen.
Und bitte, bitte sollte man die Daten nicht aufteilen. Daten sind viel komplizierter zu verwalten als Code.
Man kann jederzeit komplexer werden als jetzt. Man kann Teile aus einem Monolithen herauslösen und zu Services machen; das ist natürlich schwierig, aber kein Vergleich dazu, bereits eingebaute Komplexität wieder aus einem System herauszuholen.
Wer schon einmal mehrere Microservices wieder in einen Monolithen zurückgeführt hat, weiß, dass der Aufwand meist ähnlich groß ist wie ein Neubau von Grund auf.
Solche Produkte könnte man, wenn man wollte, wirklich auf einem Laptop in Produktion betreiben.
Bei einem früheren Arbeitgeber gab es für 300 Kunden ein Microservice-Fest. Und das, obwohl das Geschäft schon mit ein paar Tausend Kunden erfolgreich und mit Zehntausenden ein Riesenerfolg gewesen wäre.
Normalerweise werden eben keine 25 % der Engineering-Zeit in die Plattformpflege gesteckt; deshalb ist es lokal nicht einmal ausführbar, und die Produktionsumgebung wird gerade so mit Gaffer-Tape zusammengehalten.
In einem aktuellen Bewerbungsgespräch wurde ich gefragt, ein System für „500 Millionen gleichzeitige Nutzer“ zu entwerfen, obwohl das Unternehmen eher in die Kategorie wenige Kunden, hoher Umsatz pro Kunde fiel.
Ich weiß bis heute nicht, ob das ein Test war, ob ich erkenne, dass 500 Millionen etwa 10 % der weltweit mit dem Internet verbundenen Bevölkerung sind und damit eine absurde Zahl, oder ob das Startup tatsächlich glaubte, es könne dahin kommen.
Ich antwortete, ich würde mich auf das Einfachste konzentrieren: einen Monolithen bauen und prüfen, ob die Funktionen und das Produkt das sind, was die Leute wollen. Ich wurde nicht eingestellt.
Ich arbeite in einem riesigen Monolithen mit etwa 800 Beitragenden, und selbst das Hinzufügen eines einfachen Feldes wie des Geburtstags eines Nutzers ist genauso kompliziert. Allerdings ist die Komplexität nicht nur technischer Natur; weil man den Code aller berührt, braucht es „organisatorische Abstimmung“.
Design und Reviews wiederholen sich endlos, mindestens 2 Architekten müssen zustimmen, und es wird in mehrere Planungszyklen aufgenommen. Der eigentliche Code dauert nicht einmal einen halben Tag.
Im Code-Review muss man 90 % Testabdeckung erreichen, aber es gibt so viele Tests, dass ein einzelner PR zu groß wäre; also wird er in mehrere PRs aufgeteilt und über mehrere wöchentliche Releases hinweg eingebracht.
Deshalb versteckt man es hinter einem Feature Flag, von denen es derzeit 13.000 gibt.
Sobald es in Produktion ist und Dashboards und Monitoring dranhängen, schaltet man es immer wieder ein und aus. Man ist sich nicht sicher, warum die Geburtstagsfunktion den Billing-Service kaputtgemacht hat, aber sie sieht nach der Ursache aus, also muss man das ein paar Wochen analysieren.
Am Ende bekommt der Engineer, der daran gearbeitet hat, ein Jahr später vielleicht eine gute Bewertung und wird zum Beförderungskandidaten. Und direkt danach wird er auf ein weiteres kaputtes Projekt gesetzt, das in sein drittes Entwicklungsjahr geht: Nutzer sollen ihre Zeitzone einstellen können.
Weder Microservices noch Monolithen sind ein Allzweckhammer oder eine Silberkugel, und umgekehrt auch nicht das Böse schlechthin. Beides sind Werkzeuge mit Trade-offs, und sie verbinden sich je nach Organisation mit anderen kontextabhängigen Trade-offs.
Das Problem ist, dass Engineers von Komplexität fasziniert sind und „Einfachheit“ mit „Behelfslösung“ verwechseln, und dass Organisationen Werkzeuge und Architektur-Patterns blind nachahmen.
Wenn man glaubt, schon der Einsatz einer Architektur oder eines Design-Patterns bringe automatisch Vorteile, und es naiv anwendet, passiert genau das nicht.
Ich habe versucht, mir einzuprägen, dass Software Engineering ein endloser Kampf gegen Komplexität ist; mal war ich erfolgreich, mal bin ich gescheitert.
Diesen Kampf muss man immer führen, und er muss oberster Wert sein. Sonst passiert so etwas.
Es gibt keine Architektur und keine Ideologie, die diesen Krieg beendet; das ist einfach das Wesen dieses Berufs.
In der Produktionsumgebung konnten diese Release-Flags nicht aktiviert werden, und Entwickler mussten den Flag-Code vor dem finalen Test und Release entfernen.
Für jede Funktion, die ein Flag braucht, entsteht dadurch ein bisschen zusätzliche Arbeit, aber schon nach ein paar Monaten zahlt sich das durch deutlich geringere Komplexität der Codebasis aus.
Microservices sind keine Lösung für ein technisches Problem, sondern für ein soziales Problem.
Ein Team mit N Engineers braucht N² Koordination. Große Teams versinken in endlosen Meetings, E-Mails und Design-Reviews; kleine Teams sind effektiver, haben aber Schwierigkeiten, große Systeme zu warten.
Teilt man ein System in Subsysteme auf, kann jedes Team sich auf sein eigenes Puzzleteil konzentrieren und die Abstimmung zwischen Menschen reduzieren.
Es stimmt, dass Microservices Komplexität und Overhead hinzufügen, aber dieser Ansatz ermöglicht großen Organisationen, große Systeme schnell zu bauen und iterativ zu verbessern.
Statt direkter Verbindungen braucht man nun „cross-funktionale“ Meetings zwischen Teams und komplexe Kommunikationsschichten.
Wenn man eine Zerlegung gefunden hat, bei der zwischen den Subsystemen kaum Verbindungen nötig sind, dann hätten diese Verbindungen auch im ursprünglichen System nicht existiert, und es hätte auch kein N²-Problem gegeben.
Was ich wiederholt gesehen habe, ist ein riesiges Team, bei dem „alle für alle Microservices verantwortlich sind“, und am Ende ist niemand für irgendetwas verantwortlich.
Um ein „Menschenproblem“ zu lösen, verwandeln sie ein triviales technisches Problem in ein komplexes Problem verteilter Systeme.
Jetzt hat man ein echtes Problem.
Es unterstützte zwei Arten von Datenbanken und hatte außerdem einen horizontal skalierbaren Job-Runner.
Früher waren wir 35 Leute, aber durch Entlassungen schrumpften wir auf 7, und genau dann begannen wir, deutlich mehr zu schaffen. Der Grund war, dass viel weniger Zeit dafür draufging, alle aufeinander abzustimmen.
Es gab viel weniger Meetings, Freigaben, Reviews, Planung, Retrospektiven und Management-Meetings; die Entwickler hatten mehr Entscheidungsspielraum und erledigten die Dinge einfach.
Features schafften wir problemlos in der Hälfte der Zeit, und die übrigen 50 % steckten wir in den Abbau technischer Schulden. Weil wir Komplexität gnadenlos reduzierten, wurden wir auch beim Hinzufügen neuer Features schneller.
Manche Projekte brauchen sicher mehr Leute, aber ich denke, es gibt eine Obergrenze für die Komplexität, die man einem System innerhalb einer bestimmten Zeit hinzufügen kann.
Wenn man über einen Schwellenwert hinaus mehr Entwickler einstellt, bleibt die Zahl der Features pro Woche gleich, aber alle arbeiten ein bisschen weniger und verbringen mehr Zeit mit Kommunikation.
Wiederholt man diesen Prozess bis zu Tausenden von Leuten, dauert es Monate, ein einziges Feld hinzuzufügen.
Ich frage mich, ob man schon einmal darüber nachgedacht hat, Dinge einfach in verschiedene Ordner zu verschieben.
Für Modularisierung braucht man kein neues Repository und kein neues Docker-Setup. Man kann einfach Ordner verwenden.
Ein häufiges Muster sieht so aus: Die heutigen CTOs oder VPs haben den ursprünglichen Monolithen gebaut oder daran mitgebaut.
Niemand möchte dem CTO sagen, dass dieser Code miserabel ist. Oder es ist einfach Code, der wegen geänderter Zeiten eine komplette Überarbeitung braucht, ganz unabhängig davon, dass er ein Monolith ist.
Der CTO ist mit Marketing oder Fundraising beschäftigt und kann nicht entscheiden, ob es Microservices oder ein Monolith sein sollen; ein neu eingestellter Architekt trifft die Entscheidung.
Alle jubeln über Microservices. Es passt gut zur Erzählung eines schnell wachsenden, ernsthaften Technologieunternehmens, und niemand möchte allein dagegen sein oder den CTO kritisieren.
Nur selten empfiehlt jemand Microservices wirklich deshalb, weil sie der beste Trade-off sind. Eher, weil man seine Arbeit mag, gern mehr Leute einstellt und es gut zur Story des Unternehmens passt.
Im Zuge einer großen Umgestaltung kann man viel Code neu schreiben und verbessern, und man nennt das einfach Migration zu Microservices.
Am Ende ist es ein Weg, ohne die Gefühle des CTO zu verletzen, der Masse zu folgen und unter einem Vorwand, den fast alle unterstützen, große Mengen alten, schlechten Codes neu zu schreiben.
Ob einzelner Lead Engineer oder CTO/Gründer: Rückblickend kommt man am Ende zu dem Schluss, dass man es besser hätte machen können, und sieht mit Freude und Schrecken zugleich die Vor- und Nachteile der Muster und Prozesse, denen das Team gewissenhaft gefolgt ist.
Mir gefällt der Beitrag umso mehr, weil er meine Voreingenommenheit bestätigt
Ich sage das seit Jahren, aber ich sehe den Microservices-Hype eher als Ausrede dafür, dass durchschnittliche Engineers ihre Nachfrage aufrechterhalten. Durchschnittlichkeit befeuert das und hält zugleich viele Tech-Unternehmen am Laufen
Es gibt nicht genug fähige Engineers, die UNIX wirklich beherrschen und schöne, minimalistische Systeme wie StackOverflow bauen können
Deshalb werden Microservices als Nebelwand für Durchschnittlichkeit bleiben. Umso mehr, weil Cloud-Anbieter wie AWS sich über jeden erdenklichen Kanal vermarkten und Entscheider dazu bringen, diesen Weg zu wählen
Wenn man nicht über Cloud, Microservices und ungeprüfte neueste Frameworks spricht, gilt man als altmodischer alter Mensch
Obwohl solche Systeme selten die effizientesten, leistungsfähigsten oder sichersten sind
Meine jetzige Firma entwickelt Software, die intern in anderen Unternehmen genutzt wird; es gibt höchstens 200 gleichzeitige Nutzer und keine Lastspitzen
Das wäre die perfekte Umgebung für einen gewöhnlichen Webserver, ohne unerwartete Skalierungsprobleme, aber alle wollen in die Cloud
Meiner Meinung nach liegt das daran, dass Management, Programmierer und sogar Kunden vom Cloud-Marketing überzeugt wurden und glauben, Cloud sei cool
Unternehmen liefern nicht nur ihr Organigramm aus, sondern auch all ihre Dysfunktionen und historischen Altlasten im Produkt
Selbst wenn es vor fünf Jahren eine schöne Plattform mit effizientem, gut designtem Datenmodell und API sowie gut geschriebenem und getestetem Code war, kann sie fünf Jahre später völlig chaotisch sein: durch ständige Kurswechsel des CEO, kurzfristig vom Vertrieb durchgedrückte Kundenwünsche, Produktmanager, die weder benötigte noch angeforderte Features hinzufügen, sowie zu wenig Personal und Zeit
Eines Tages steht man vor einem riesigen Haufen Technical Debt, Bugfixes und neue Features dauern unnötig lange, und Microservices klingen wie der Sirenengesang, der einem zuflüstert, dass man nicht alles niederbrennen und von vorne anfangen muss
Das mag wie Haarspalterei wirken, hat aber einen größeren Punkt: Die Technologiewahl ist selten der Engpass
Microservices sind dagegen wegen mehr beweglicher Teile und Fehlermodi deutlich komplexer, sodass durchschnittliche Engineers – und auch viele nicht durchschnittliche – viel eher Probleme verursachen
Offenbar haben wir es versäumt, der aktuellen Generation richtig beizubringen, worauf es bei dieser Arbeit ankommt
Ich kann das nachvollziehen, weil wir in einem kleinen Team gerade auf Microservices umstellen. Das größte Problem ist Observability
Wenn im Betrieb etwas schiefgeht, wird es zu enormer Fleißarbeit, genau herauszufinden, was falschgelaufen ist
Es reicht nicht, die Logs einer verteilten Anwendung nachzuverfolgen; man muss gleichzeitig die Logs mehrerer verteilter Anwendungen betrachten, deren Nachrichten sich gegenseitig vermischen
Wenn wir Tools hätten, die Traces visualisieren, wäre es in Ordnung, aber als kleines Team haben wir nur begrenzte personelle Bandbreite und solche Tools noch nicht
Im Monolithen dagegen war NewRelic seit Jahren integriert. Es gab Performance-Probleme, aber die meisten wurden mit Indizes und ein paar materialisierten Views gelöst
Es ist leicht zu erkennen, was schiefgelaufen ist, und selbst wenn der Code alt und voller Race Conditions ist, ist die Fehlerbehebung selbst nicht schwierig
Ich fürchte den Zeitpunkt, an dem jede Microservice-Komponente eine eigene Datenbankinstanz hat und später aktualisiert werden muss. Ich hätte mir gewünscht, mehrere Datenbanken auf einer einzigen Datenbankinstanz zu haben, aber diese Architektur steht nicht zur Auswahl
Zentralisiertes Logging und Tracing von Service-Aufrufen/Codeausführung sind nichts Neues. Sie werden nur oft auf später verschoben, bis man in genau so einer unangenehmen Lage landet
Weil die richtigen Tools nicht von Anfang an eingebaut wurden, ist das Team kleiner und stärker eingeschränkt, weil es kaum oder gar nicht weiß, was die Services tun
Datenbankinstanzen kann man einzeln upgraden. Wenn es keinen schwerwiegenden Bug etwa in der Sicherheit gibt, muss man sich nicht beeilen, nur weil ein Upgrade möglich ist
Wenn ich solche Texte lese, fühlt sich das auf seltsame Weise therapeutisch an. Vor zehn Jahren habe ich dasselbe laut gesagt, wurde aber als Ungläubiger behandelt und mir wurde gesagt, ich solle still sein
Man möge mir nachsehen, dass das „Microservices“-Paradigma einen bitteren Nachgeschmack hinterlassen hat. Ich habe am eigenen Leib erlebt, was passiert, wenn man die Trade-offs der neuesten Modetechnologie nicht vollständig versteht und sie trotzdem komplett übernimmt
Als ich vor langer Zeit bei StumbleUpon eingestellt wurde, war das gerade die Zeit, in der ein angeblich führender promovierter Informatiker den gut laufenden und profitablen PHP-Monolithen in eine Scala/Java-Microservices-Architektur umwandeln wollte
Zum Onboarding gehörte auch ein seltsames 1:1 mit diesem verrückten Informatiker; er pries wortreich die Vorteile von Microservices an und wich Fragen wie „Warum sollten wir einen verteilten Service bauen, nur um eine Liste von Zahlen zu addieren?“ geschickt mit einer Geste nach dem Motto „Du wirst nicht verstehen, warum das viel besser ist“ aus
Nach mehr als 30 Neueinstellungen und über vier Jahren intensiver Entwicklung blieb dem Unternehmen, das inzwischen nicht mehr profitabel war, nur noch eine langsamere, fehleranfälligere und nicht debuggbare verteilte Hölle
Der Gesamt-Designer und Architekt entschied damals, dass dies ein guter Zeitpunkt für ein „Sabbatical“ sei, und kurz darauf war auch die wievielte Finanzierungsrunde auch immer aufgebraucht, sodass alle sich Jobs suchen mussten
Um die Amtrak-Metapher aus dem Artikel aufzugreifen: Dieser Text ist völlig entgleist.
Der Autor setzt voraus, dass es auf magische Weise in Ordnung gewesen wäre, wenn man statt mieser Microservices einfach einen Monolithen gebaut hätte.
Als ob mit demselben Niveau an Design und Engineering, mit dem man Schrott-Microservices gebaut hat, ein goldenes Ergebnis herausgekommen wäre, wenn nur das Ziel ein Monolith gewesen wäre.
Zwischendurch ist der Text auch ziemlich selbstgefällig; der Kommentar zu Full-Stack-JS-Entwicklern ist ein Beispiel dafür.
Tatsächliche Inhalte aus Engineering-Sicht gibt es aber kaum. Man hofft auf Messwerte oder Daten, bekommt aber nur eine Tirade.
Komplexität zu beherrschen, um die Kosten von Systemänderungen niedrig zu halten, ist ein gutes Ziel, aber das schlägt dieser Artikel nicht vor.
Hätte er das eingeräumt oder Daten oder wenigstens eine Anekdote geliefert, wäre der Text besser gewesen.
In unserem Team würden wir eher einen aufgeweckten, engagierten Frontend-Entwickler wählen, der seinen Horizont erweitern und zu einem Full-Stack-Entwickler wachsen möchte, als jemanden, der glaubt, bereits alles zu wissen und sich nicht mehr weiterentwickeln zu müssen.
An meinem aktuellen Arbeitsplatz kämpfen wir gegen diesen Trend an; bei manchen Teams mit einigem Erfolg, bei anderen deutlich weniger. Diese Teams kämpfen jetzt mit dem verteilten Monolithen, den sie selbst geschaffen haben.
Ironischerweise sind alle ehemaligen FAANMG-Leute eher auf der Seite der Monolithen-Befürworter.
Viele übersehen offenbar, dass Microservices das Ergebnis eines iterativen Prozesses sind. Am Ende trennt man die Teile aus dem Monolithen heraus, die skaliert werden müssen.
Microservices erfordern viel Basisinfrastruktur, die man nur dann betreiben möchte, wenn man sie wirklich braucht.
Die meisten Unternehmen haben auch nicht die passende Plattform, um dieses Muster zu unterstützen.
Kann ich nachvollziehen. In unserem Unternehmen haben wir das Debugging praktisch aufgegeben, weil die Tools nicht richtig funktionieren.
Um einen einzigen Service auf der lokalen Maschine auszuführen, muss man die übrigen neun so konfigurieren, dass sie mit diesem Service verbunden sind.
Wenn man dann noch ein „Feature“ für Kunden baut, muss man natürlich mindestens zwei Services gleichzeitig anfassen und noch mehr Daten hin- und herschieben.
Setzt man auf der einen Seite einen Breakpoint, läuft die andere Seite in ein Timeout.
Also deployen alle Entwickler Release-Builds in eine lokale VM, streuen ohne Hot Reload console.log, System.PrintLines() und _logger ein und lesen verstreute Logdateien.
Natürlich werde ich das sinkende Schiff verlassen.
Noch besser wäre es, vollständig auf Distributed Tracing umzusteigen, aber um Requests sauber nachverfolgen zu können, müsste man die Tracing-Metadaten überall vereinheitlichen, was eine größere Investition ist.
Das hilft wahrscheinlich eher im Betrieb als in der Entwicklung, aber hilfreich wäre es trotzdem. Schon ordentliche Span-Informationen liefern viele Einblicke, um das Chaos zu verstehen.
Wenn ein Breakpoint auf der einen Seite auf der anderen Seite ein Timeout verursacht, frage ich mich, ob es im Entwicklungsmodus keine Möglichkeit gibt, Timeouts zu erhöhen oder abzuschalten.