Be Software Architecture Wise
Be Wise Apps

Read in English · Leer en español · Lire en français

Abschnitt 6.8 von 6.8 · Mittelstufe · 28 Min. Lesezeit

Serverless und Space-Based Architecture

Videolektion

5 Min. · auf Englisch gesprochen, mit Untertiteln
Nur anhören (Audio)
Transkript lesen

Diese Lektion behandelt zwei Stile, die die Kapazitätsfrage gegensätzlich beantworten. Serverless zahlt nur für die Nutzung. Space-Based Architecture bedient extreme Spitzen aus dem Arbeitsspeicher. Beide sind Spezialwerkzeuge, und beide werden oft aus den falschen Gründen gewählt.

Ein Taxistand berechnet nur jede einzelne Fahrt. Braucht niemand eine Fahrt, zahlen Sie nichts, aber in einer belebten Nacht kostet jede Fahrt mehr als ein eigenes Auto. Und das erste Taxi braucht vielleicht einen Moment, bis es kommt. Das ist Serverless. Stellen Sie sich nun eine Stadionkasse vor einem riesigen Konzert vor. Statt dass jeder Kassierer ein zentrales Verzeichnis prüft, führt jeder Schalter seine eigene Kopie der freien Plätze und meldet seine Verkäufe später an das Backoffice. Das ist Space-Based Architecture, gebaut für den Ansturm.

Serverless heißt nicht, dass es keine Server gibt. Es heißt, dass Ihr Team keine Server bereitstellt, patcht, dimensioniert oder für ungenutzte bezahlt. Bei Function as a Service lösen Ereignisse kleine Stücke Ihres eigenen Codes aus. Hier lösen eine Webanfrage, eine Queue-Nachricht, ein hochgeladenes Foto und ein nächtlicher Zeitplan jeweils eine Funktion aus, deren Instanzen der Anbieter erzeugt, skaliert und wieder abbaut. Bei Backend as a Service ersetzen vollständig verwaltete Dienste serverseitige Teile: eine Datenbank, E-Mail und Dateispeicher. Funktionen sind zustandslos und kurzlebig. Aller dauerhafte Zustand liegt in verwalteten Diensten, daher ist ein Serverless-System von seiner Bauart her ein verteiltes System.

Ohne Verkehr läuft nichts, und keine Rechenleistung wird berechnet. Wenn Ereignisse eintreffen, starten viele Instanzen parallel, und tausend davon können eine Datenbank mit Verbindungen überfordern. Sie zahlen pro Anfrage, plus Arbeitsspeicher mal Laufzeit. Code, der auf eine langsame API wartet, zahlt fürs Warten. Die erste Anfrage an eine neue Instanz wartet, während diese startet, von einigen zehn Millisekunden bis zu mehreren Sekunden. Diese Kaltstarts treffen plötzliche Lastspitzen am härtesten. Funktionen behalten zwischen Aufrufen nichts, laufen unter harten Grenzen, und viele Auslöser stellen mindestens einmal zu, daher müssen Handler idempotent sein. Und Serverless bindet Sie eng an Ihren Anbieter. Ein Mittelweg: Halten Sie die Geschäftslogik in einfachen Modulen hinter Ports, mit schlanken Funktions-Handlern als Adapter.

Ist es günstiger? Der Abschnitt rechnet es mit erfundenen runden Beispielpreisen durch, nicht mit echten Preisen eines Anbieters. Zwei dauerhaft laufende virtuelle Maschinen und ein Load Balancer kosten pauschal hundert Pfund im Monat. Als Funktionen kostet dieselbe Speisekarten-API etwa drei Pfund zwanzig pro Million Anfragen, steigend mit dem Verkehr. Die Linien kreuzen sich bei etwa einunddreißig Millionen Anfragen im Monat, rund zwölf pro Sekunde. Darunter ist Serverless günstiger, weil Leerlauf nichts kostet. Darüber zahlt ein gleichmäßig ausgelasteter Service mehr. Das lässt das Personal außen vor, dessen Zeit mehr kosten kann als die Differenz. Rechnen Sie also mit echten Preisen und gemessenem Verkehr nach.

Space-Based Architecture nimmt die Datenbank, die sonst jede Anfrage berührt, vom Hot Path. Hier, bei einem Ticket-Vorverkaufsstart, leitet ein Messaging Grid die Anfrage jedes Käufers an eine Processing Unit. Jede identische Einheit hält Logik und Platzdaten im Arbeitsspeicher, und ein Data Grid repliziert Änderungen zwischen den Einheiten. Änderungen erreichen die Datenbank später: Data Pumps reihen sie ein, und Data Writer schreiben sie. Data Reader laden beim Start Daten aus der Datenbank, um das Grid vorzuwärmen. Der Haken sind Datenkollisionen: Zwei Einheiten können dasselbe Element aktualisieren, bevor die Replikation nachgezogen hat. Für Daten, die niemals kollidieren dürfen, etwa den letzten Platz, leiten Sie alle zugehörigen Anfragen an eine Einheit.

Stellen Sie sich vor, der Vorverkauf einer Stadiontour beginnt um zehn Uhr, und etwa vierhunderttausend Menschen warten. Das System darf nie einen Platz doppelt verkaufen und darf nicht zusammenbrechen. Anfragen werden nach Vorstellung und Block geleitet, sodass eine Einheit alle Reservierungen für einen Block bearbeitet. Reservierungen können nie kollidieren. Wählt ein Käufer zwei Plätze, reserviert die Einheit sie für acht Minuten, im Arbeitsspeicher, in Mikrosekunden. Die Zahlung läuft mit einem Idempotenzschlüssel. Bei Erfolg werden die Plätze als verkauft markiert, und eine Data Pump reiht den Verkauf ein. Die Datenbank wird in einem gleichmäßigen Tempo beschrieben, das sie durchhält, und die Queue ist einige Minuten nach der Spitze abgearbeitet. Kein Käufer wartet auf die Datenbank.

Serverless passt zu sprunghafter, unvorhersehbarer oder geringvolumiger Arbeit, ereignisgesteuertem Glue-Code, geplanten Jobs und Teams ohne Betriebskapazität. Schlecht passt es zu gleichmäßigem, hochvolumigem Verkehr, lang laufenden Prozessen und strenger Tail-Latenz, die Kaltstarts verletzen würden. Space-Based Architecture ist komplex und teuer, und die Datenbank hinkt dem Grid hinterher. Setzen Sie sie nur für extreme Spitzen ein. Versuchen Sie zuerst Caching, Lesereplikate oder einen virtuellen Warteraum, der Käufer in kontrolliertem Tempo einlässt. Das ist weit einfacher und reicht allein oft aus.

Damit ist Kapitel 6 abgeschlossen. Wenn Sie so weit sind, legen Sie den optionalen Kapiteltest ab: zwanzig Multiple-Choice-Fragen und zwei schriftliche Antworten, mit einer Bestehensgrenze von achtzig Prozent. Gehen Sie dann weiter zu Kapitel 7 über Datenarchitektur. Bis gleich.

Was Sie wissen müssen

Zwei Antworten auf die Kapazitätsfrage

Jeder Stil in diesem Kapitel ging bisher davon aus, dass jemand Server betreibt und für die Last dimensioniert. Dieser Abschnitt behandelt zwei Stile, die die Kapazitätsfrage gegensätzlich beantworten. Serverless-Architektur überlässt die Server vollständig einem Cloud-Anbieter und zahlt pro Nutzung, was zu Arbeit passt, die klein, ereignisgesteuert und oft untätig ist. Space-Based Architecture hält alles, was eine stark belastete Anfrage braucht, im Arbeitsspeicher, verteilt auf viele identische Einheiten, sodass die Datenbank nicht mehr auf dem Hot Path liegt; das passt zu extremen und plötzlichen Spitzen wie einem Ticket-Vorverkaufsstart. Beide sind Spezialwerkzeuge; beide werden oft aus den falschen Gründen gewählt.

Serverless: Funktionen und verwaltete Backends

Serverless bedeutet nicht, dass es keine Server gibt; es bedeutet, dass das Team keine Server bereitstellt, patcht, dimensioniert oder für ungenutzte Server zahlt. Mike Roberts’ viel zitierter Artikel von 2018 unterscheidet zwei Zutaten. Function as a Service (FaaS) führt kleine Stücke des eigenen Codes des Teams als Reaktion auf Ereignisse aus, in Containern, die der Anbieter erzeugt, skaliert und wieder abbaut und die womöglich nur für einen einzigen Aufruf existieren. AWS Lambda, im November 2014 angekündigt und seit April 2015 allgemein verfügbar, machte das Modell zum Mainstream; Azure Functions, Google Cloud Run functions und Cloudflare Workers sind weitere Beispiele. Backend as a Service (BaaS) ersetzt serverseitige Komponenten durch vollständig verwaltete Dienste Dritter, die der Client oder die Funktion direkt aufruft: Authentifizierung (Auth0, Amazon Cognito), Datenbanken (Firebase, DynamoDB), Objektspeicher, E-Mail und Queues.

Eine Serverless-Anwendung ist meist eine Kombination: Funktionen enthalten die Geschäftslogik, die für die Organisation spezifisch ist, und alles andere, einschließlich des gesamten dauerhaften Zustands, liegt in verwalteten Diensten. Der Anbieter kümmert sich um Kapazität, Verfügbarkeit über Zonen hinweg und das Betriebssystem. Das Team bleibt verantwortlich für seinen Code, seine Daten, seine Konfiguration und seine Sicherheitseinstellungen, wie das Modell der geteilten Verantwortung in Server und die Cloud erklärt.

Ereignisse lösen Funktionen aus; der Zustand liegt anderswo

Ereignisquellen wie ein HTTP-Gateway, eine Queue, ein Objektspeicher und ein Scheduler lösen zustandslose Funktionen aus, die ihren Zustand in Managed Services haltenHTTP-GatewayPOST /ordersBestellunganlegenQueueOrderPlacedBeleg sendenFunktionObjektspeicherSpeisekartenfoto neuThumbnailserzeugenSchedulerjede Nacht 02:00AuszahlungenabrechnenEreignisquellenFunktionen (FaaS)Managed Services (BaaS)Managed DatabaseBest. + Auszahl.E-Mail-DienstBelegeObjektspeicherBilderJede Funktionsinstanz ist zustandslos und kurzlebig; aller dauerhafte Zustand liegt in Managed Services
In einer Essenslieferplattform lösen vier Arten von Ereignissen vier Funktionen aus, die in Managed Services lesen und schreiben, statt selbst etwas zu behalten.

Wie Funktionen sich verhalten: die Eigenschaften, die den Entwurf prägen

Ereignisauslöser. Funktionen laufen als Reaktion auf Ereignisse: eine HTTP-Anfrage über ein Gateway, eine Nachricht in einer Queue oder einem Stream, eine Datei, die im Objektspeicher landet, eine Datenbankänderung oder einen Zeitplan. Auslöser, die die Funktion asynchron aufrufen, etwa Queues und Speicherbenachrichtigungen, stellen typischerweise mindestens einmal zu und wiederholen bei Fehlern; Handler müssen daher idempotent sein, genau wie in ereignisgesteuerte Architektur.

Auf null und in die Breite skalieren. Ohne Verkehr läuft keine Instanz, und für Rechenleistung wird nichts berechnet. Wenn Ereignisse eintreffen, startet die Plattform parallel weitere Instanzen, bis zu einem Konto- oder Funktionslimit für Nebenläufigkeit; bei AWS Lambda liegt das regionale Standardlimit zum Zeitpunkt der Erstellung bei 1000 gleichzeitigen Ausführungen und lässt sich auf Antrag anheben. Schnelles Hochskalieren ist Feature und Gefahr zugleich: Tausend gleichzeitige Funktionen können tausend Datenbankverbindungen öffnen und eine relationale Datenbank überfordern, die für einige hundert ausgelegt ist; deshalb gibt es Verbindungsproxys und Nebenläufigkeitsgrenzen pro Funktion.

Abrechnung pro Aufruf. Die Kosten bestehen meist aus einer kleinen Gebühr pro Anfrage plus einer Gebühr für Arbeitsspeicher multipliziert mit der Ausführungszeit (Gigabyte-Sekunden). Code, der untätig auf eine langsame nachgelagerte API wartet, zahlt also fürs Warten.

Kaltstarts. Die erste Anfrage an eine neue Instanz muss warten, während die Plattform einen Container startet, die Laufzeitumgebung lädt und den Initialisierungscode ausführt: von einigen zehn Millisekunden bis zu mehreren Sekunden, je nach Sprache, Paketgröße und Netzwerkkonfiguration. Instanzen werden für spätere Anfragen wiederverwendet, solange sie warm sind; Kaltstarts treffen daher seltenen Verkehr und plötzliche Lastspitzen am härtesten. Gegenmittel sind kleinere Deployment-Pakete, leichtere Laufzeitumgebungen, Initialisierung außerhalb des Handlers und das Bezahlen dafür, Instanzen vorinitialisiert zu halten (AWS nennt das Provisioned Concurrency), was teilweise wieder Kosten für Dauerbetrieb einführt.

Grenzen. Funktionen laufen unter harten Grenzen für Ausführungszeit, Arbeitsspeicher, Payload-Größe und temporären Speicherplatz; für AWS Lambda zum Zeitpunkt der Erstellung 15 Minuten, 128 MB bis 10.240 MB Arbeitsspeicher (mit proportional zugeteilter CPU) und 6 MB für eine synchrone Anfrage oder Antwort. Lange Jobs müssen in Schritte zerlegt und große Payloads per Referenz auf den Objektspeicher übergeben werden.

Zustandslosigkeit. Nichts im Arbeitsspeicher oder auf der lokalen Festplatte einer Instanz überlebt garantiert bis zum nächsten Aufruf. Caching im Arbeitsspeicher zwischen Aufrufen ist eine Optimierung, die trifft oder auch nicht, nie ein Ort für Daten, auf die es ankommt.

Wohin der Zustand kommt

Weil Funktionen nichts behalten, verlagert sich die Architekturarbeit auf die Wahl, wo jede Art von Zustand liegt. Dauerhafte Geschäftsdaten kommen in eine verwaltete Datenbank, oft eine, die viele kurzlebige Verbindungen gut verkraftet (Key-Value- oder Dokumentspeicher oder eine relationale Datenbank hinter einem Verbindungsproxy). Große Objekte kommen in den Objektspeicher und werden zwischen Funktionen per Schlüssel übergeben. Kurzlebiger gemeinsamer Zustand, etwa Zähler für Rate Limiting, kommt in einen verwalteten Cache. Der Fortschritt eines mehrstufigen Prozesses kommt in einen Workflow-Dienst (AWS Step Functions, Azure Durable Functions oder Ähnliches), der als dauerhafter Saga-Orchestrator fungiert, wie in Sagas beschrieben. Benutzersitzungen kommen in Tokens, die der Client hält, oder in einen Session Store.

Die Folge: Ein Serverless-System ist von seiner Bauart her ein verteiltes System, mit allen Anliegen dieses Kapitels: Netzwerklatenz zwischen jeder Funktion und ihren Daten, Teilausfälle, doppelte Ereignisse, Eventual Consistency und der Bedarf an verteiltem Tracing. Eine einzige Geschäftsaktion kann ein Gateway, drei Funktionen, eine Queue und zwei Datenbanken durchlaufen. Observability (siehe Observability) ist nicht optional.

Anbieterkopplung: der Preis dafür, keine Server zu betreiben

Serverless koppelt ein System enger an seinen Anbieter als das Mieten virtueller Maschinen oder der Betrieb von Containern. Ereignisformate, Auslöserkonfiguration, Identitäts- und Berechtigungsmodelle, Workflow-Definitionen und die verwalteten Dienste selbst sind allesamt anbieterspezifisch. Eine ausgereifte Serverless-Anwendung in eine andere Cloud zu bringen, ähnelt eher einer Neuentwicklung als einer Migration.

Fachleute sind uneins, wie sehr das zählt. Die eine Sicht lautet, Lock-in sei der Preis für eine große Entlastung im Betrieb, und die meisten Organisationen wechselten nie die Cloud, sodass die Optimierung auf Portabilität Aufwand verschwende. Die andere hält dagegen, dass Preisänderungen, regulatorische Anforderungen oder Übernahmen sehr wohl einen Wechsel erzwingen und dass tiefe Kopplung Verhandlungsmacht nimmt. Ein Mittelweg besteht darin, Kopplung an den Rändern zu akzeptieren und im Kern einzudämmen: Halten Sie die Geschäftslogik in einfachen Modulen hinter Ports, mit schlanken Funktions-Handlern als Adapter (der Ansatz der hexagonalen Architektur), pflegen Sie Infrastructure as Code, und halten Sie die Kopplung als explizite Entscheidung fest. Kosten und Lock-in werden in FinOps und Lock-in weiter erörtert.

Ausgearbeitetes Beispiel

Ausgearbeitetes Beispiel: Wann wird Dauerbetrieb günstiger?

Die Speisekarten-API der Essenslieferplattform könnte als Funktionen oder auf zwei dauerhaft laufenden virtuellen Maschinen laufen. Alle Preise sind erfundene runde Zahlen, die der Rechnung dienen, keine aktuellen Listenpreise irgendeines Anbieters. Jede Anfrage läuft im Schnitt 200 ms mit 0,5 GB Arbeitsspeicher und verbraucht also 0,1 GB-Sekunden.

Beispielpreise ServerlessRechenleistung £0,00002 pro GB-Sekunde; £0,20 pro Million Aufrufe; £1,00 pro Million Anfragen über das HTTP-Gateway.
Serverless-Kosten pro Million AnfragenRechenleistung: 1.000.000 × 0,1 GB-s × £0,00002 = £2,00. Aufrufe £0,20. Gateway £1,00. Insgesamt £3,20 pro Million.
Beispielkosten DauerbetriebZwei kleine VMs zu je £40 im Monat (zwei für Redundanz) plus ein Load Balancer zu £20 = £100 im Monat, dimensioniert für Spitzen von etwa 300 Anfragen pro Sekunde.
1 Million Anfragen im Monat (im Schnitt 0,4 pro Sekunde)Serverless £3,20; Dauerbetrieb £100. Serverless ist etwa 30-mal günstiger.
10 Millionen im Monat (etwa 4 pro Sekunde)Serverless £32; Dauerbetrieb £100.
Break-even£100 ÷ £3,20 ≈ 31 Millionen Anfragen im Monat, im Schnitt etwa 12 Anfragen pro Sekunde (31,25 Millionen ÷ 2,59 Millionen Sekunden in 30 Tagen).
100 Millionen im Monat (etwa 39 pro Sekunde)Serverless £320; Dauerbetrieb weiterhin £100, weil zwei VMs noch Reserven haben.
Wirkung einer Halbierung der Laufzeit auf 100 msDie Rechenkosten fallen auf £1,00, insgesamt £2,20 pro Million, und der Break-even verschiebt sich auf etwa 45 Millionen. Optimierung zahlt sich bei Serverless direkt aus.

Unterhalb des Break-even ist Serverless günstiger, weil Leerlauf nichts kostet; oberhalb zahlt ein gleichmäßig ausgelasteter Service mehr für dieselbe Arbeit. Stoßweiser Verkehr mit langen Leerlaufphasen spricht auch bei höheren Volumen für Serverless.

Der reine Vergleich lässt für viele Teams den größten Kostenpunkt weg: das Personal. Patchen, Skalieren und Rufbereitschaft für VMs können leicht mehr kosten als die Differenz, was den tatsächlichen Break-even nach oben verschiebt. Kosten für Datenübertragung, Logging und Observability fallen bei beiden an und sind oft höher als jede der beiden Rechenrechnungen.

Weil das Ergebnis von Laufzeit, Arbeitsspeicher, Verkehrsprofil und aktuellen Preisen abhängt, wiederholen Sie die Rechnung vor der Entscheidung mit echten Preisen und gemessenem Verkehr, und erneut, wenn der Verkehr wächst.

Der Break-even als Grafik

Liniendiagramm der Beispielkosten pro Monat über den Anfragen pro Monat: Serverless-Kosten steigen linear und schneiden die fixen Kosten des Dauerbetriebs bei etwa 31 Mio. Anfragen im Monat0255075100£0£100£200£300Anfragen pro Monat (Millionen)Monats-kostenDauerbetrieb: £100 fixServerless: £3,20 pro MillionBreak-even bei etwa 31 Mio.(etwa 12 Anfragen pro Sekunde)
Mit diesen Beispielpreisen wachsen die Serverless-Kosten um £3,20 pro Million Anfragen und erreichen die fixen £100 des Dauerbetriebs bei etwa 31 Millionen Anfragen im Monat.

Wann Serverless passt und wann nicht

Serverless passt zu sprunghaften, unvorhersehbaren oder geringvolumigen Workloads, bei denen das Bezahlen ungenutzter Server Verschwendung ist; zu ereignisgesteuertem Glue-Code, etwa der Reaktion auf Uploads, Queue-Nachrichten und Datenbankänderungen; zu geplanten Jobs und Backoffice-Automatisierung; zu Prototypen und neuen Produkten, bei denen das Team seine Zeit in das Produkt statt in die Infrastruktur stecken sollte; und zu Teams ohne Plattform- oder Betriebskapazität.

Schlecht passt es zu gleichmäßigem, hochvolumigem Verkehr, bei dem die Preise pro Anfrage die dauerhaft laufende Kapazität übertreffen (wie im ausgearbeiteten Beispiel); zu lang laufenden oder zustandsbehafteten Prozessen, etwa Videotranscoding über das Zeitlimit hinaus oder WebSocket-Servern mit vielen Verbindungen; zu strengen Anforderungen an niedrige Tail-Latenz, die Kaltstarts verletzen würden; zu Workloads, die Spezialhardware oder feine Kontrolle über die Laufzeitumgebung brauchen; und zu feingranularen Entwürfen, in denen viele Funktionen einander synchron aufrufen, was bei jedem Schritt Netzwerk-Hops, Kosten und Fehlerquellen hinzufügt. Kapitel 1 beschrieb, wie Amazon Prime Video 2023 einen Monitoring-Service von verteilten Serverless-Schritten auf einen einzigen Prozess umstellte und eine Senkung der Infrastrukturkosten um über 90 % meldete (Warum Architektur zählt): kein Urteil über Serverless, aber eine Erinnerung daran, dass Passung mehr zählt als Mode.

Space-Based Architecture: die Datenbank vom Hot Path nehmen

Die meisten Architekturen skalieren Web- und Anwendungsschicht problemlos, stoßen aber irgendwann an die Datenbank, die jede Anfrage berührt. Mehr Server davor verlagern die Warteschlange nur zur Datenbank. Space-Based Architecture, wie Mark Richards und Neal Ford sie in Fundamentals of Software Architecture beschreiben, nimmt die Datenbank ganz aus dem synchronen Pfad. Jede Anfrage wird vollständig im Arbeitsspeicher von einer von vielen identischen Processing Units bearbeitet, und die Datenbank wird asynchron im Hintergrund aktualisiert.

Der Name stammt vom Tuple Space, einem gemeinsamen assoziativen Speicher, den David Gelernters Koordinationssprache Linda 1985 einführte: Prozesse kommunizieren, indem sie Tupel in einen gemeinsamen Raum schreiben und passende Tupel lesen oder herausnehmen, ohne voneinander zu wissen. Suns JavaSpaces brachte die Idee Ende der 1990er-Jahre zu Java, und kommerzielle Plattformen bauten darauf verteilte, replizierte Spaces auf, aus denen sich die heutigen In-Memory Data Grids wie Hazelcast, Apache Ignite und Oracle Coherence entwickelten.

Die Teile eines Space-Based-Systems

  1. Processing UnitEine deploybare Einheit mit der Anwendungslogik und einem In-Memory Data Grid, das die von dieser Logik benötigten Daten hält, dazu eine Replikations-Engine. Die Einheiten sind identisch, also bringt jede zusätzliche Einheit mehr Kapazität. Im Ticketbeispiel hält jede Einheit den Saalplan und die aktuellen Reservierungen für die Veranstaltungen, die sie bedient.
  2. Virtualisierte MiddlewareDie Infrastruktur, die die Einheiten verwaltet. Das Messaging Grid nimmt Anfragen entgegen und leitet jede an eine verfügbare Einheit. Das Data Grid repliziert Änderungen zwischen den In-Memory-Kopien der Einheiten. Das optionale Processing Grid koordiniert Anfragen, die mehrere Arten von Einheiten brauchen. Der Deployment Manager startet und stoppt Einheiten, wenn die Last steigt und fällt.
  3. Data PumpsAsynchrone Kanäle, meist persistente Message Queues, die jede in einer Einheit vorgenommene Änderung zur Datenbankseite transportieren. Ist die Datenbank langsam oder ausgefallen, warten die Änderungen in der Queue; die Käufer merken davon nichts.
  4. Data WriterKomponenten, die die Nachrichten der Pumps konsumieren und die Änderungen in die Datenbank schreiben. Sie lassen sich unabhängig von den Einheiten skalieren und pausieren.
  5. Data ReaderKomponenten, die Daten aus der Datenbank in die Einheiten laden, wenn das Grid kalt startet, zum Beispiel nachdem jede Einheit neu gestartet oder neu deployt wurde. Bei der normalen Verarbeitung von Anfragen werden sie nicht verwendet.

Space-Based Architecture für einen Ticket-Vorverkaufsstart

Space-Based Architecture: Anfragen werden an Processing Units geleitet, die Daten in einem replizierten In-Memory-Grid halten; Updates fließen asynchron über Data Pumps und Data Writer in die DatenbankTicketkäuferVirtualisierte MiddlewareMessaging Grid: leitet AnfragenDeployment ManagerProcessing Unit 1Logik + PlatzdatenIn-Memory-GridProcessing Unit 2Logik + PlatzdatenIn-Memory-GridProcessing Unit 3Logik + PlatzdatenIn-Memory-GridData Grid: repliziert Änderungen der EinheitenData PumpsData WriterDatenbankData ReaderLaden beim Start
Anfragen werden von identischen Processing Units aus dem Arbeitsspeicher bedient; die Datenbank wird asynchron über Data Pumps und Data Writer aktualisiert und nur gelesen, um das Grid vorzuwärmen.

Datenkollisionen und andere Kosten

Replizierte Kopien in vielen Einheiten bringen die Konsistenzprobleme aus den vorigen Abschnitten in den Arbeitsspeicher. Bei einem replizierten Cache hat jede Einheit eine vollständige Kopie, und Änderungen werden asynchron kopiert; das ergibt schnelle lokale Lesezugriffe, aber zwei Einheiten können dasselbe Element aktualisieren, bevor die Replikation nachgezogen hat. Richards und Ford nennen das eine Datenkollision und schätzen ihre Rate als Zahl der Einheiten mal Quadrat der Update-Rate, geteilt durch die Zahl der Elemente, mal Replikationslatenz. Bei 5 Einheiten, 20 Updates pro Sekunde, 50.000 Elementen und 100 ms Latenz sind das 5 × 400 ÷ 50.000 × 0,1 = 0,004 pro Sekunde, etwa 115 Kollisionen an einem Achtstundentag; eine Senkung der Latenz auf 1 ms bringt das auf etwa eine.

Für Daten, die niemals kollidieren dürfen, etwa den letzten Platz in einer Reihe, gibt es zwei Alternativen: einen verteilten Cache, in dem jedes Element in einer Partition liegt und jede Einheit es dort liest und schreibt (konsistent, aber jeder Zugriff ist ein Netzwerkaufruf, und die Partitionen des Grids müssen verfügbar bleiben), oder das Routing aller Anfragen für eine Veranstaltung oder einen Block an dieselbe Einheit, sodass nur eine einzige Einheit diese Plätze je ändert. Die meisten realen Entwürfe kombinieren beides: Sie partitionieren die heißen, umkämpften Daten nach Schlüssel und replizieren überwiegend gelesene Daten wie Saalpläne und Preise.

Die übrigen Kosten sind erheblich. Daten im Arbeitsspeicher sind durch dessen Größe begrenzt und müssen nach einem vollständigen Neustart wieder aufgebaut werden. Die Datenbank ist mit dem Grid nur letztendlich konsistent, sodass Reporting und andere Systeme Änderungen verspätet sehen, und der Verlust eingereihter Änderungen ist ein reales Risiko, das die Dauerhaftigkeit der Pumps abdecken muss. Tests unter realistischer Spitzenlast sind teuer und schwierig. Und der Stil ist komplex und kostspielig im Aufbau: Richards und Ford bewerten ihn niedrig bei Einfachheit und Testbarkeit und hoch bei den Kosten. Er lohnt sich nur, wenn sich die Last wirklich nicht mit Caching, Lesereplikaten und einer gut abgestimmten Datenbank bedienen lässt.

Ausgearbeitetes Beispiel

Ausgearbeitetes Beispiel: ein Vorverkaufsstart im Stadion

Der Vorverkauf für eine Stadiontour beginnt um 10:00. Etwa 400.000 Menschen warten; in den ersten zehn Minuten liegt die Nachfrage beim Hundertfachen der normalen Rate und mehr, dann ebbt sie ab. Das Ticketsystem darf keinen Platz doppelt verkaufen und darf nicht zusammenbrechen.

Vor dem VorverkaufsstartData Reader laden die Saalpläne jeder Vorstellung in das Grid. Der Deployment Manager startet genug Processing Units für die prognostizierte Spitze.
RoutingDas Messaging Grid leitet Anfragen nach Vorstellung und Block, sodass alle Reservierungen für Block 112 der Samstagsvorstellung von derselben Einheit bearbeitet werden. Platzreservierungen kollidieren nie.
Ein Käufer wählt zwei PlätzeDie Einheit markiert sie für diesen Käufer 8 Minuten lang als HELD, im Arbeitsspeicher, in Mikrosekunden, und antwortet. Die Saalpläne für andere Käufer werden über die Replikation aktualisiert.
Aus der Reservierung wird ein VerkaufDer Zahlungsschritt läuft (ein externer Aufruf mit Idempotenzschlüssel); bei Erfolg markiert die Einheit die Plätze als SOLD, und eine Data Pump reiht den Verkauf ein.
Die DatenbankData Writer schreiben die Verkäufe in einem gleichmäßigen Tempo, das die Datenbank durchhält. Während der Spitze wächst die Queue; einige Minuten nach dem Nachlassen der Nachfrage ist sie abgearbeitet. Keine Käuferanfrage wartet auf die Datenbank.
Eine Reservierung läuft abDie Einheit gibt die Plätze im Arbeitsspeicher frei; die Pump reiht einen Freigabedatensatz ein.

Viele Ticketsysteme schalten zusätzlich einen virtuellen Warteraum vor den Verkauf, der Käufer in kontrolliertem Tempo einlässt. Das ist weit einfacher und reicht allein oft aus; Space-Based Architecture ist für den Fall gedacht, dass schon die eingelassene Last für einen datenbankzentrierten Entwurf zu hoch ist.

Das Routing nach Block ist die Entwurfsentscheidung, die das Kollisionsproblem für die wichtigsten Daten von „selten, aber möglich“ zu „unmöglich“ macht.

Eigenschaften im Vergleich (qualitativ, für typische Entwürfe)

MerkmalServerless (FaaS und BaaS)Space-Based
ElastizitätSehr hoch, automatisch, einschließlich Skalierung auf nullSehr hoch bei Spitzen, aber Einheiten brauchen Zeit zum Starten und Laden der Daten
PerformanceGut im warmen Zustand; Kaltstarts und Netzwerk-Hops erhöhen die LatenzSehr hoch: Anfragen werden aus dem Arbeitsspeicher bedient
KostenprofilZahlung pro Nutzung; hervorragend bei Leerlauf oder Spitzen, teuer bei gleichmäßiger AuslastungHoch: viele Einheiten, viel Arbeitsspeicher, komplexe Middleware, Dauerbetrieb
EinfachheitEinfach pro Funktion; das Gesamtsystem kann unübersichtlich werdenNiedrig: Replikation, Kollisionen, Pumps und Laden beim Kaltstart
KonsistenzWas die verwalteten Datenspeicher bietenDie Replikation im Arbeitsspeicher ist letztendlich konsistent, sofern umkämpfte Daten nicht partitioniert sind; die Datenbank hinkt hinterher
TestbarkeitEinheiten sind leicht zu testen; Integrationstests brauchen Cloud-UmgebungenSchwierig: realistische Spitzenlasttests sind teuer
BetriebsaufwandNiedrig für die Infrastruktur; hoch für Observability und GrenzenHoch
ÜbertragbarkeitNiedrig: anbieterspezifische Auslöser und DiensteMittel: hängt vom Data-Grid-Produkt ab

Checkliste: bevor Sie sich für Serverless oder Space-Based entscheiden

Beantworten Sie diese Fragen, wo möglich, mit gemessenen Zahlen.

  • VerkehrsprofilIst die Last sprunghaft, über weite Strecken null oder gleichmäßig? Serverless belohnt Leerlauf; Space-Based belohnt extreme Spitzen; gleichmäßige Last spricht für gewöhnliche, dauerhaft laufende Services.
  • Kosten-Break-evenHaben Sie die Kosten pro Anfrage gegen die Kosten des Dauerbetriebs mit echten Preisen, Laufzeiten und Verkehrszahlen berechnet, einschließlich Gateway, Datenübertragung und Personal?
  • LatenzbudgetVerkraftet die langsamste akzeptable Antwort einen Kaltstart oder den Netzwerk-Hop zu dem Ort, an dem der Zustand liegt?
  • GrenzenÜberschreiten Jobs die Grenzen für Ausführungszeit, Arbeitsspeicher oder Payload? Lassen sie sich in Schritte zerlegen oder per Referenz übergeben?
  • Zustand und VerbindungenWo liegt jede Art von Zustand, und kommen die Datenspeicher mit plötzlichen Schüben gleichzeitiger Verbindungen zurecht?
  • IdempotenzKann jeder Handler gefahrlos zweimal für dasselbe Ereignis laufen?
  • Konkurrenz um DatenWelche Daten sind bei Space-Based-Entwürfen umkämpft, und werden sie so partitioniert oder geroutet, dass sie nicht kollidieren können?
  • Dauerhaftigkeit der VerzögerungWas geht verloren, wenn das Grid oder die Pumps ausfallen? Sind die Pumps persistent, und ist die Verzögerung der Datenbank für Reporting und andere Systeme akzeptabel?
  • Einfachere AlternativenWürden Caching, Lesereplikate, eine Queue vor der Datenbank oder ein virtueller Warteraum den Bedarf mit weniger Komplexität decken?
  • Lock-in-EntscheidungIst die Kopplung an den Anbieter oder das Grid-Produkt als bewusste Entscheidung festgehalten, mit der Geschäftslogik hinter Ports?

Prüfen Sie Ihr Verständnis

Warum muss eine von einer Queue ausgelöste Funktion idempotent sein?

Weil asynchrone Auslöser typischerweise mindestens einmal zustellen und bei Fehlern wiederholen, sodass dasselbe Ereignis die Funktion mehr als einmal aufrufen kann.

Wie viel würden 50 Millionen Anfragen im Monat mit den Beispielpreisen aus dem ausgearbeiteten Beispiel bei Serverless ungefähr kosten, und welche Option ist günstiger?

50 × £3,20 = £160 im Monat; die Option im Dauerbetrieb zu £100 ist also bei den reinen Infrastrukturkosten günstiger, bevor Personal und weitere Gebühren mitgerechnet werden.

Welche Aufgabe haben Data Reader bei Space-Based Architecture, und wann?

Sie laden Daten aus der Datenbank in die In-Memory-Grids der Processing Units, wenn das Grid kalt startet, etwa nach einem vollständigen Neustart oder Redeployment; für normale Anfragen werden sie nicht verwendet.

Wie hilft es, alle Anfragen für einen Stadionblock an eine Processing Unit zu leiten?

Nur diese Einheit ändert je diese Plätze, sodass zwei Einheiten nicht denselben Platz aktualisieren können, bevor die Replikation nachgezogen hat; damit sind Datenkollisionen für diese Daten ausgeschlossen.

Ende von Kapitel 6Den Kapiteltest ablegenOptional: 20 Multiple-Choice-Fragen und 2 schriftliche Antworten, in der App.Zum Test →

Quellen und weiterführende Literatur

Haben Sie eine Frage zu diesem Abschnitt? ArchitectBot, der KI-Lernassistent des Kurses, antwortet zuerst aus dem Kurs.

Fragen: „Unsere Ticketseite bricht jedes Mal zusammen, wenn der Vorverkauf für eine große Show beginnt. Sollten wir auf Serverless, auf Space-Based Architecture oder auf etwas Einfacheres wie einen Warteraum umsteigen?“