- Unkey, ein Anbieter von API-Authentifizierungsdiensten, wechselte von einer serverlosen Architektur auf Basis von Cloudflare Workers zu zustandsbehafteten Servern auf Go-Basis, um Performance-Probleme und architektonische Komplexität zu lösen
- Die neue Struktur bietet 6-mal schnellere Antwortzeiten und beseitigt zugleich komplexe Cache-Workarounds sowie den Overhead von Datenpipelines
- In einer serverlosen Umgebung gab es keine Garantie für persistenten Speicher zwischen Funktionsaufrufen, sodass jeder Cache-Lesevorgang eine Netzwerkanfrage erforderte und eine Cache-Latenz von über 30 ms bei p99 verursachte
- Durch den Wechsel von einem verteilten System zu einer einfachen Anwendungsarchitektur wurde Self-Hosting möglich, Plattformunabhängigkeit erreicht und die Developer Experience deutlich verbessert
- Serverless eignet sich für unregelmäßige Workloads oder einfache Request/Response-Muster, aber wenn konsistent niedrige Latenz oder persistenter Zustand erforderlich sind, sind zustandsbehaftete Server effektiver
Grenzen von Serverless und Performance-Engpässe
- Bei Unkey liegt die API-Authentifizierung im kritischen Pfad jeder Anfrage, daher wirken sich Verzögerungen im Millisekundenbereich direkt auf die User Experience aus
- Die weltweite Edge-Bereitstellung und automatische Skalierung von Cloudflare Workers waren attraktiv, doch fehlende Cache-Persistenz und Latenz durch Netzwerkanfragen erwiesen sich als Problem
-
Caching-Probleme
- Serverlose Funktionen haben keinen persistenten Speicher zwischen Aufrufen, daher ist für jeden Cache-Zugriff eine externe Netzwerkanfrage nötig
- Die p99-Latenz für Cloudflare-Cache-Lookups wurde mit über 30 ms gemessen
- Selbst mit mehreren Cache-Schichten (SWR, Redis usw.) kann es grundsätzlich nicht schneller sein als „0 Netzwerkanfragen“
- Dadurch ließ sich das angestrebte Antwortziel von unter 10 ms nicht erreichen
-
Probleme durch SaaS-Kopplung
- Serverless reduziert zwar den Aufwand für das Infrastrukturmanagement, in der Praxis werden jedoch zusätzliche SaaS-Tools unverzichtbar
- Cache → Redis, Batch-Verarbeitung → Queue, Logs → Durable Objects usw.
- Jeder Dienst fügt Latenz, Kosten und zusätzliche Fehlerquellen hinzu
- Trotz gemischter Nutzung von Cloudflare Durable Objects, Queues und Workflows nahm die tatsächliche Komplexität sogar noch zu
-
Probleme mit der Datenpipeline
- Da Serverless eine flüchtige Umgebung ist, müssen bei jedem Aufruf Daten sofort geschrieben werden
- Um Events, Logs und Metriken zu verarbeiten, musste ein komplexer Buffering- und Relay-Service direkt selbst aufgebaut werden
- Beispiel:
- Batch-Versand von Logs an ClickHouse über
chproxy
- Aufbau eines separaten Buffering-Servers, um beim Senden von Logs an Axiom Rate Limits zu umgehen
- Das führte dazu, dass selbst einfache Analysefunktionen die Komplexität eines verteilten Event-Processing-Systems erreichten
Wechsel zu zustandsbehafteten Servern
- Mit der Einführung eines zustandsbehafteten Go-Servers (v2) wurden In-Memory-Batching und periodisches Flushen möglich
- Zusätzliche Dienste oder komplexe Pipelines sind nicht mehr erforderlich
- Wartbarkeit, Debugging und lokale Tests wurden erheblich vereinfacht
-
Performance-Ergebnisse
- Beim Vergleich von
/v1/keys.verifyKey und /v2/keys.verifyKey wurde eine 6-fach geringere Latenz gemessen
- Trotz weniger Infrastruktur als bei den 300 globalen Cloudflare-POPs verbesserte sich die wahrgenommene Performance für Nutzer deutlich
Vorteile über die Performance hinaus
-
Self-Hosting
- Durch die Abhängigkeit von der Cloudflare-Runtime konnten Kunden Unkey nicht selbst hosten
- Die Workers-Runtime ist zwar technisch Open Source, aber lokale Ausführung ist selbst im Entwicklungsmodus äußerst schwierig
- Mit dem Wechsel zu einem Standard-Go-Server wurde Self-Hosting einfach
- Ausführung mit nur dem Befehl
docker run -p 8080:8080 unkey/api möglich
- Keine spezielle Runtime und keine komplexe Konfiguration erforderlich
- Entwickler können nun innerhalb weniger Sekunden den kompletten Unkey-Stack lokal ausführen, was Debugging und Tests deutlich erleichtert
- Lokale Entwicklung und Debugging wurden drastisch beschleunigt
-
Verbesserte Developer Experience
- Einschränkungen unter Serverless:
- Berücksichtigung von Limits bei der Funktionsausführung
- Schwierige Zustandsverwaltung zwischen Aufrufen
- Komplexes Debugging verteilter Logs
- Unbequeme lokale Testumgebung
- Mit dem Wechsel zu zustandsbehafteten Servern entfiel diese Complexity Tax
-
Plattformunabhängigkeit
- Keine Bindung mehr an das Cloudflare-Ökosystem
- Bereitstellung überall möglich
- Beliebige Datenbanken nutzbar
- Integration von Drittanbieterdiensten ohne Sorgen um Runtime-Kompatibilität
Migrationsstrategie und Erkenntnisse
- Die Migration wurde als Gelegenheit genutzt, über die Zeit angesammelte Probleme im API-Design zu korrigieren
- Die neue v2-API läuft parallel zur bestehenden v1, sodass Kunden beide Versionen während des Deprecation-Zeitraums verwenden können
- Ein Vorteil des Beibehaltens von Serverless ist, dass der Betrieb der v1-API auch bei auf null sinkender Nutzung nicht viel kostet, wodurch ein kostenloses Migrationsfenster möglich wurde
-
Was beibehalten wurde
- Nicht alles am serverlosen Ansatz wurde verworfen
- Globale Edge-Bereitstellung: Mit AWS Global Accelerator bleibt die Latenz weltweit niedrig
- Automatische Skalierung: Fargate übernimmt das Skalieren ohne die Einschränkungen von Serverless
-
Verbesserte Performance des Rate Limiters
- Im serverlosen Modell waren erhebliche Trade-offs zwischen Geschwindigkeit, Genauigkeit und Kosten nötig; aufgrund der verteilten Natur war es fast unmöglich, alle drei gleichzeitig zu erreichen
- Mit zustandsbehafteten Servern und In-Memory-Status wurde ein Rate Limiter gebaut, der schneller und genauer ist und zugleich die Betriebskosten senkt
Wann Serverless geeignet ist – und wann nicht
-
Wann Serverless geeignet ist
- Unregelmäßige Workloads: Wenn nicht dauerhaft Rechenleistung benötigt wird, ist die Wirtschaftlichkeit durch Skalierung auf null hervorragend
- Einfache Request/Response-Muster: Wenn kein persistenter Zustand und keine komplexe Datenpipeline nötig sind
- Event-getriebene Architekturen: Hervorragend geeignet, um ohne Infrastrukturmanagement auf Events zu reagieren
-
Wann Serverless ungeeignet ist
- Wenn konsistent niedrige Latenz erforderlich ist: Externe Netzwerkabhängigkeiten verschlechtern die Performance
- Wenn persistenter Zustand erforderlich ist: Workarounds für Zustandslosigkeit erhöhen die Komplexität
- Bei hochfrequenten Workloads: Das Abrechnungsmodell pro Aufruf ist unwirtschaftlich
- Wenn feingranulare Kontrolle nötig ist: Die Abstraktion der Plattform kann zur Einschränkung werden
-
Kosten der Komplexität
- Die wichtigste Lehre der Migration war, die Komplexitätskosten von Workarounds für Plattformbeschränkungen zu verstehen
-
Was unter Serverless gebaut wurde
- Eine ausgefeilte Caching-Bibliothek, um die Zustandslosigkeit zu umgehen
- Mehrere Hilfsdienste für die Batch-Verarbeitung von Daten
- Eine komplexe Log-Pipeline zur Erfassung von Metriken
- Ausgefeilte Workarounds für die lokale Entwicklung
-
Bei zustandsbehafteten Servern
- All das fällt weg
- Der Wechsel von einem verteilten System mit vielen beweglichen Teilen zu einer einfachen Anwendungsarchitektur
- Manchmal ist es die beste Lösung, eine andere Grundlage zu wählen, statt Beschränkungen zu umgehen
Nächste Schritte
- Derzeit läuft Unkey auf AWS Fargate hinter Global Accelerator, das ist jedoch nur eine Zwischenlösung
- Im nächsten Jahr soll die eigene Bereitstellungsplattform „Unkey Deploy“ erscheinen, mit der Kunden – und Unkey selbst – Unkey überall dort ausführen können, wo sie möchten
- Der Wechsel zu zustandsbehafteten Go-Servern ist der erste Schritt, um Unkey wirklich portabel und self-hosting-fähig zu machen
- Implementierungsdetails sind als Open Source im GitHub-Repository verfügbar
3 Kommentare
Ich war früher fast so etwas wie ein gläubiger Verfechter von Serverless-Architekturen, aber in letzter Zeit bevorzuge ich eher eine Struktur, die aus einer einzelnen EC2-Instanz und einer einzelnen RDS-Instanz besteht. Und dann löse ich nach und nach nur das heraus, was wirklich benötigt wird. Die Einführung von Serverless ist für mich inzwischen etwas, das ich erst nach gründlicher Überlegung angehe.
Es gibt dafür verschiedene Gründe, aber schon wenn nur eine Person im Team kein Wissen über Serverless hat, steigen die Kosten für Kommunikation und Wartung erheblich. Und als ich wieder klassische Server betrieben habe, wurde mir erneut bewusst, dass Serverless weder so günstig noch so bequem war, wie ich zunächst gedacht hatte.
Hacker-News-Kommentare
Als jemand, der einige Jahre mit Serverless-Umgebungen gearbeitet hat (hauptsächlich Amazon Lambda, aber auch anderes), stimme ich dem Autor ausdrücklich zu
Serverless nimmt einem an manchen Stellen Arbeit ab, aber gleichzeitig hat man in anderen Bereichen mehr Arbeit, weil man „künstlich entstehende Probleme“ lösen muss
Ein Beispiel bei mir war das Problem mit Upload-Größenbeschränkungen
Als wir eine bestehende Anwendung auf Serverless umgestellt haben, dachte ich, es würde reichen, einen API-Endpunkt für den Import großer Kundendaten anzulegen und einen Hintergrund-Worker dahinterzuhängen
Aber beim „API Gateway“ (dem Proxy, der den Code aufruft) waren Uploads über 100 MB nicht möglich, und als ich fragte, ob man das Limit ändern könne, wurde mir einfach gesagt, ich solle die Kunden anweisen, kleinere Dateien hochzuladen
Technisch klingt das vielleicht plausibel, aber in der Realität werden echte Kunden ihr Upload-Verhalten nicht ändern
Es fühlt sich eher an wie „funktioniert im Vakuum“: theoretisch klingt es toll, aber in der Praxis investiert man die mit Serverless eingesparte Zeit und das eingesparte Geld am Ende wieder darin, Serverless-spezifische Probleme zu lösen
Um das zu lösen, sollte man presigned S3-URLs bereitstellen
Man kann es so anbinden, dass Nutzer direkt zu S3 hochladen und danach das Upload-Ergebnis übermitteln, oder die Dateinamen etwa über eine Request-ID unterscheiden
Als jemand, der schon lange mit AWS arbeitet, finde ich das zwar lästig, aber wenn man eine beliebige Datei-Upload-API offenlässt, ist das DoS-Risiko groß, daher ist das 100-MB-Limit an sich nachvollziehbar
Wenn man allerdings bedenkt, wie schnell das Internet heute ist, wirkt die 100-MB-Grenze etwas aus der Zeit gefallen
Trotzdem finde ich, dass es irgendwann eine Begrenzung geben muss
Unsere Firma war zeitweise der Kunde, der die AWS-Abteilung für SSL-Zertifikate praktisch repräsentiert hat
Um Vanity-URLs (Custom Domains) zu unterstützen, brauchten wir für jede Domain ein SSL-Zertifikat, also Tausende davon
Das Zertifikats-Management-Tool von AWS war aber nur bis zu einigen Hundert wirklich komfortabel nutzbar, daher hat es etwa drei Monate gedauert, bis dieses Problem gelöst war
Es war überraschend, dass einige AWS-Services nicht schnell auf Anforderungen reagieren konnten, die nur von sehr wenigen Kunden kamen
Anfangs sah Lambda extrem vielversprechend aus, also haben wir es eingeführt, aber am Ende haben wir alle Lambda-Projekte aufgegeben und je nach Bedarf in Container-Umgebungen verschoben
Auch bei Lambda muss man die Node-Runtime alle 1–2 Jahre aktualisieren, und mit Containern ist man flexibler, weil man den Zyklus selbst bestimmen kann
Das schwierigste Problem der Informatik ist es, Dateien von einem Computer auf einen anderen zu kopieren
Für künftige Leser hier noch ein Hinweis
Mit dem „tus“-Uploader und passenden Endpoints bekommt man Funktionen wie Chunking und Resume beim Upload und kann solche Limits gut umgehen
https://tus.io/
Wie im Artikel beschrieben, hat Serverless definitiv seinen eigenen Einsatzzweck
Aber ich denke, für die meisten Anwendungen ist es nicht geeignet
Außer in besonderen Fällen plane ich nicht, Serverless als Kerninfrastruktur zu verwenden
In der Praxis wirkt es eher so, als würde die Infrastrukturverwaltung dadurch noch umständlicher
Jede Plattform hat andere Anforderungen, und auch Test- und Entwicklungsabläufe unterscheiden sich stark, sodass alles immer etwas vage ist und lokales Testen schwierig bleibt
Auch die Abstraktionsschichten haben auf jeder Plattform ihre Fallstricke, und es gibt keinen echten Standard
Es ist bequemer, ausführbare Artefakte als Docker-Images zu paketieren, und auch die Umgebung lässt sich damit ausreichend abstrahieren, was sich für mich natürlicher anfühlt
Das Minimum an Abstraktion auf Linux-Umgebungs- und Dateisystemebene erscheint mir am effizientesten
Bei Bedarf kann man dieses Image dann auf einem Server starten und on demand oder dauerhaft im Standby betreiben
Wenn man sich die vielen Technologie-Trends der letzten zehn Jahre ansieht, waren oft genau die Dinge erfolgreich, die große Unternehmen eingesetzt haben, um Probleme zu lösen, die real nur in ihrer eigenen Größenordnung existieren
Beispiele wären GraphQL, react, Tailwind, NextJS und andere
Kein Tool ist ein Allheilmittel für jedes Problem, und wichtig ist, auf Basis von Erfahrung und Verständnis der eigenen Situation zu entscheiden
Ich wünschte, ich könnte erzählen, wie „unterhaltsam“ es gerade ist, eine Amazon-Lambda-App lokal zum Laufen zu bringen
Es vor dem Deployment zu testen, ist schon für sich eine Herausforderung
Knative (Serverless für Kubernetes) nimmt Container direkt an
Weil es ein Standard-Paketformat ist, lässt es sich leicht auf verschiedene Plattformen verschieben
Das Team dort entwickelte in Wirklichkeit keine Anwendung, sondern eine Bibliothek, die in zustandsbehaftete Serveranwendungen integriert werden sollte
Auch der Performance-Vorteil kam daher, dass die Authentifizierung nahe an der Kundenumgebung verarbeitet wurde, nicht wegen Serverless an sich
Akzeptieren nicht eigentlich alle „Serverless“-Plattformen Docker-Images?
Soweit ich weiß, unterstützt Cloud Run das
Eigentlich geht es um die Sorge, dass „Serverless Functions“ zu viel abstrahieren
ClickHouse mag nicht Tausende kleiner Inserts, deshalb sammeln wir mit einem Go-Service namens chproxy Events und schicken sie in großen Batches
Jeder Cloudflare Worker sendet Analytics-Events an chproxy, und chproxy bündelt sie und überträgt sie gesammelt an ClickHouse
Statt eigens einen separaten Service nur für ClickHouse-Daten zu bauen, gab es doch auch die Funktion für asynchrone Inserts — ich frage mich, warum die nicht genutzt wurde
https://clickhouse.com/docs/optimize/asynchronous-inserts
Entwickler scheinen von Tools umgeben zu sein, die angeblich „alles vereinfachen“
Tatsächlich lassen sich die meisten Probleme auch mit den grundlegendsten Werkzeugen (Compiler, bash-Skripte, Bibliotheken) leicht lösen
Diese Fixierung auf Werkzeuge kann am Ende sowohl Unternehmen als auch Entwicklern eher schaden
Meiner Meinung nach war Docker im Jahr 2013 das letzte Tool, das wirklich universelle und positive Veränderungen gebracht hat
Seitdem gibt es zwar Dinge, die einzelnen Unternehmen helfen können, aber wenn man versucht, sie auf alle Unternehmen anzuwenden, bricht oft eher die Produktivität ein oder das System fällt auseinander
Heute versuchen Firmen wie Cloudflare, v8 isolates als „nächstes Docker“ zu positionieren, aber das passt nur für bestimmte Workloads, nicht für alles
Das Muster „Docker-Image entgegennehmen und ins Internet stellen“ ist so mächtig, dass es meiner Meinung nach selbst 2040 noch die stärkste Variante sein wird
Ein Problem ist auch, dass es immer weniger Leute mit solidem Fundament gibt
Die Arbeit läuft zunehmend so, dass der Großteil des Stacks an Drittanbieter-Services ausgelagert wird und man selbst nur noch Teile der Kernanwendung baut
Sogar das könnte irgendwann von KI geschrieben werden
Die gesamte Branche kultiviert gerade eine Art „erlernte Hilflosigkeit“
Erstaunlich viele Leute kennen sich mit Compilern, bash-Skripten und Bibliotheken nicht gut aus
AWS Lambda ist fast zu billig
Für die Steigerung der Bekanntheit hilft es aber!
Ich habe noch niemanden gesehen, der mit bash-Skripten den Staff-Rang erreicht hat
Ich würde gern den „vercel security checkpoint“ etwas fragen
Wenn ich auf dem iPhone mit Proton VPN und Firefox Focus über Exit-Nodes in Kalifornien oder Kanada zugreife, bekomme ich ständig den Fehler code 99 „Failed to verify your browser“
Woran liegt das?
Dieser Thread bestätigt meinen Eindruck
Der Begriff Serverless ist so unscharf definiert, dass schon der Name selbst unsinnig wirkt
Server existieren schließlich weiterhin
Es ist ein bisschen wie der Ausdruck „ohne Strom“, obwohl tatsächlich Strom verwendet wird
Der Name wurde nur geändert, ohne zu sagen, was eigentlich wirklich passiert
Ich denke nicht, dass die einzige Schlussfolgerung „Serverless ist schlecht“ sein sollte
Die wichtigere Lehre ist, dass ein Dienst mit Abhängigkeiten selbst dann unerwartet langsam in der End-to-End-Erfahrung werden kann, wenn man ihn näher an den Client verlagert, solange man diese Abhängigkeiten nicht mitverlagert
Im Prinzip ist es besser, nahe an den Abhängigkeiten zu bauen, und wenn das nicht reicht, müsste man alle Abhängigkeiten zum Client bringen oder synchronisieren — in der Praxis wird das aber oft viel zu komplex
Es hängt davon ab, wie und wie oft die Abhängigkeiten genutzt werden, und bei Datenbanken etwa kann es je nach Zweck sinnvoller sein, näher am Server oder näher am Client zu sein
Manche Nutzungsszenarien brauchen schnelle Antworten, bei anderen ist Langsamkeit akzeptabel
Je nachdem, was sich auf Server- oder Client-Seite cachen lässt, kann man das auch anders aufteilen
Ich glaube nicht, dass man das streng binär betrachten sollte
Wenn man das beste Preis-Leistungs-Verhältnis will, ist die richtige Antwort, eigene Instanzen aufzusetzen und selbst genau die Arbeit zu erledigen, die man braucht
Man muss die Cloud-Anbieter nicht zu überteuerten Abrechnungszauberern werden lassen
Das aktuelle „lokale Maximum“, das wir erreicht haben, besteht darin, Docker-Container als Standardumgebung bzw. Standardartefakt für Deployments zu verwenden und bei Bedarf nur noch Secrets einzuspeisen
Dadurch wird lokales Testen einfach, und die meisten zentralen Vorteile wie Infrastrukturautomatisierung und Reproduzierbarkeit bleiben erhalten
Serverless ist für die meisten Apps ein zu extremer Ansatz, passt aber gut zu manchen
Vor allem für einfache Utilities oder On-Demand-Services ohne eigene Infrastruktur sowie für große stateless Apps kann Serverless besser passen
Das heißt nicht, dass Serverless nur für einfache Einsatzzwecke taugt; ich denke eher, dass es einen grundlegenden Widerspruch zwischen dem „traditionellen Webapp“-Modell und Serverless-Plattformen gibt
Ich glaube, ich bin jetzt bereit für misterio
https://github.com/daitangio/misterio
Ein einfacher Wrapper für zustandslose Docker-Cluster
Es hat in meinem Homelab angefangen, aber dann viel Aufmerksamkeit bekommen
Docker ist ein bisschen wie Microservices
Für manche Anwendungen passt es, aber es wurde zu stark als Industriestandard vermarktet
Wenn man Docker übermäßig einsetzt, entstehen Aufwand für Security-Patches und Betrieb, und wenn man es ohne Nachdenken für jedes Projekt nimmt, scheitert man am Risikomanagement
Abhängigkeitsprobleme lösen die meisten Entwickler heute ohnehin durch Muster ohne globale Installationen
Docker ist nicht mehr so zwingend notwendig wie früher, bleibt aber weiterhin Mainstream
Aus Sicht von Hosting-Anbietern dürfte die Einführung von Docker die Marge wohl um mindestens 10 % erhöhen
Ich habe das Gefühl, dass Docker ebenfalls zu der weiter unten erwähnten „Tool-Fixierung“ gehört
Der Punkt ist nicht, dass Serverless nicht funktioniert, sondern dass die Autoren ihre eigene Grundlage nicht gut verstanden haben
Eine latenzsensitive API auf eine zustandslose Edge-Runtime zu setzen, ist ein Anfängerfehler, und das daraus resultierende Leid war durchaus vorhersehbar
Meiner Erfahrung nach entstehen die meisten Probleme mit Cloud-Services aus architektonischem Missbrauch oder Missverständnissen
Es sind menschliche Probleme, die sich mit sorgfältigerem Design oft hätten vermeiden lassen
Das Problem ist allerdings, dass Cloud-Anbieter ihre Produkte meist mit plausibel klingendem Marketing verkaufen und reale Performance-Zahlen verbergen
Ob Lambdas für meinen Workload wirklich schnell genug sind oder ob AWS-RDS-External-Replication geeignet ist, weiß man erst nach Tests
Ich habe aus Erfahrung gelernt, dass man die reale Performance von AWS selbst benchmarken muss
Es geht nicht darum, dass die Autoren es nicht verstanden hätten — schon die Tatsache, dass jemand diese Informationen geteilt hat, ist wertvoll
Ich glaube nicht, dass man das einfach als „Anfängerfehler“ abtun kann
In der Praxis wissen Ingenieure oft sehr wohl, dass ein bestimmter Ansatz für den realen Betrieb ungeeignet ist, und trotzdem drücken Manager ihn leicht durch mit der Begründung „so macht man es heute“
Oder man ist wegen Zeit- und Budgetgrenzen gezwungen, eine schlechtere Wahl zu treffen
Oder das ursprüngliche Implementierungsteam wusste es tatsächlich nicht besser — aber unabhängig davon hilft das Teilen solcher Geschichten unserer gesamten Community enorm weiter
Wenn ich aus meiner Erfahrung etwas Verlässliches brauche (schnelles Auto-Scaling, geringe Latenz, CPU-, Disk- oder Netzwerkgeschwindigkeit usw.), ist das Selbstverwalten von EC2-Instanzen am zuverlässigsten
Wenn man Kontrolle abgibt und zugleich bessere Performance erwartet, handelt man sich leicht einen nicht behebbaren Engpass ein
Letztlich bedeutet das nur, dass die Autoren „einer der heutigen 10.000“ sind
https://xkcd.com/1053/
Ich persönlich bin dankbar, dass sie diese Informationen und Fehler geteilt haben
Engineering ist immer ein Kampf um Kosten
Anfangs nutzt man es, um den Zeitaufwand für Prototyping oder den Aufbau des Geschäfts zu verringern
Später muss man durch Optimierung die Kosten senken
Schon so ein Artikel an sich beweist, wie wenig man ein Ingenieur ist
So so