Blog
TIL, dass AWS Lambda Instanzen präemptiv beendet

TL;DR: Es gibt eine Menge Artikel und Blogbeiträge über die Verhinderung oder Verkürzung von Kaltstarts für AWS Lambda-Instanzen. Ich habe gelernt, dass AWS Lambda den Kaltstart dennoch erzwingt, indem aktive, laufende Instanzen alle zwei Stunden beendet werden.
AWS Lambda ist eine ereignisgesteuerte, serverlose Computing-Plattform, die von Amazon bereitgestellt wird. Sie führt Code als Reaktion auf Ereignisse aus und verwaltet alle von diesem Code benötigten Rechenressourcen. Es ist bekannt, dass AWS im Rahmen seiner Verantwortung für die Verwaltung von Rechenressourcen im Leerlauf befindliche Lambda-Instanzen beendet. Ich habe herausgefunden, dass AWS auch aktive, laufende Instanzen beendet, und zwar ziemlich vorhersehbar.
Ressourcen effizient verwalten: Beenden passiver Instanzen
Wie bereits erwähnt, beendet AWS Lambda Instanzen, die für einige Zeit im Leerlauf sind, in der Regel etwas länger als 10 Minuten. AWS verwaltet seine Infrastrukturressourcen effizient und weist Instanzen, die nicht laufen oder seit einiger Zeit nicht mehr laufen, keine Rechenressourcen zu.
Das Ergebnis einer beendeten Lambda-Instanz ist, dass Lambda, sobald ein neues Ereignis eintrifft, eine neue Anwendungsinstanz bereitstellen, den Code des Entwicklers abrufen und in dieser Instanz bereitstellen und die Instanz starten muss, um auf den Aufruf zu reagieren.
Verständlicherweise nimmt all dies mehr Zeit in Anspruch, als wenn Sie nur auf ein Ereignis einer bereits laufenden Instanz reagieren. Abhängig von der Größe der Instanz und der Sprache dauern diese sogenannten Kaltstarts etwa
Vermeidung der Nachteile von Kaltstarts
Da diese zusätzliche Antwortlatenz nicht für alle Anwendungsfälle akzeptabel ist - sie ist besonders unangenehm, wenn die Lambda-Funktion auf eine vom Benutzer initiierte Anfrage reagieren muss - bietet AWS seit Dezember 2019 Provisioned Concurrency für Lambda an. Aber schon vorher und auch weiterhin versuchen viele Entwickler, Kaltstarts in der On-Demand-Einrichtung zu verhindern, indem sie z. B. periodische, zeitgesteuerte Ereignisse verwenden, um die Funktionen "warm" zu halten. Außerdem versuchen andere, die Gesamtzeit der Kaltstarts zu reduzieren.An Artikeln über die Vermeidung oder Beschleunigung vonKaltstartsherrscht kein Mangel .
AWS Lambda beendet Instanzen ohnehin präemptiv
Es mag Sie nicht überraschen, wenn Sie darüber nachdenken, aber vor kurzem musste ich mit Erstaunen feststellen, dass AWS Lambda auch "warme" Instanzen aktiv und präventiv beendet, während sie noch Datenverkehr empfangen. Und dass es wenig gibt, was ein Entwickler dagegen tun kann, außer vielleicht Provisioned Concurrency zu aktivieren. Ungeachtet anderer Bemühungen, die Instanzen "warm" zu halten, beendet Lambda die Instanzen nach einer gewissen Zeit und sorgt so aktiv für Kaltstarts, wenn es auf einen nächsten Aufruf reagiert.
Übrigens sollte das eigentlich keine Rolle spielen, abgesehen von dem Nachteil der gelegentlichen Kaltstartverzögerung. Bei der Einzelereignisverarbeitung von Lambda sollte sich ein Entwickler nicht um die Lebensdauer einer Lambda-Instanz kümmern und sich auch nicht darauf verlassen, dass eine bestimmte Lambda-Instanz während ihrer Existenz mehrere Ereignisse verarbeiten kann. (Sie könnten in der Lambda-Funktion eine Zwischenspeicherung einrichten, die auf der hohen Wahrscheinlichkeit beruht, dass eine Instanz eine Weile bestehen bleibt, aber dann würden Sie gegen das Ausführungsmodell von AWS Lambda verstoßen).
Dennoch war ich neugierig auf die maximale Lebensdauer einer AWS Lambda-Instanz und darauf, ob Lambda laufende Instanzen nach einiger Zeit vorhersehbar oder nur zufällig beendet. Ich konnte keine Dokumentation oder andere Blogbeiträge über die durchschnittliche Lebensdauer einer Lambda-Instanz finden, also habe ich es selbst herausgefunden.
Erstellen eines Experiments zur Untersuchung von Instanzabbrüchen
Wenn mir eine solche Frage gestellt wird, stelle ich gerne ein Experiment auf die Beine, um die Sache zu untersuchen. Für dieses Experiment war der Aufbau recht einfach. Ich habe eine Lambda-Funktion mit einem Python-Code erstellt, der erkennt, ob er in einer frisch erstellten Instanz läuft oder in einer, die bereits Anfragen bedient hat. Wenn ja, würde der Code einige Metriken protokollieren. Ich stellte diesen Code für AWS Lambda in drei verschiedenen Regionen und für mehrere Instanzgrößen bereit und richtete ein paar Tage lang ein stetiges Rinnsal von Anfragen an alle bereitgestellten Lambdas ein.
Die Besonderheiten des Experiments:
- Ich habe eine kleine, einzelne Codedatei in Python 3.7 mit einer Gesamtpaketgröße von weniger als 5 KB verwendet.
- Ich habe den Code mithilfe des Serverless Frameworks auf AWS Lambda bereitgestellt.
- Ich habe drei AWS-Regionen verwendet:
us-east-1(Nord-Virginia)eu-west-1(Irland)ap-southeast-1(Singapur)
- Die Größen der AWS Lambda-Instanzen wurden mit 256 MB, 512 MB, 1024 MB und 2048 MB festgelegt.
- Hinweis: Der tatsächlich von der Funktion verwendete Speicherplatz betrug weniger als 100 MB.
- Die Häufigkeit der Anfragen an die Lambda-Funktionen wurde so eingestellt, dass eine Lambda-Funktion alle 1, 2, 3, 4, 5, 10 und 15 Minuten über geplante Ereignisse aufgerufen wird. Zur endgültigen Überprüfung habe ich außerdem alle 10 Sekunden Anfragen an eine Lambda-Funktion gesendet.
Durchführung des Experiments
Nachdem ich das Experiment installiert und gestartet hatte, begann das Warten auf die Ergebnisse. Ich habe zwei Experimente durchgeführt, eines für zwei Tage und eines für sieben Tage. Die Experimente erstreckten sich nicht über eine Monatsgrenze und während der Experimente ereigneten sich keine drastischen, bemerkenswerten Ereignisse in der Welt. Im Nachhinein betrachtet ist das ziemlich bemerkenswert, wenn man bedenkt, dass wir uns im Jahr 2020 befinden, aber keine ungewöhnlichen Verkehrsmuster (weder hohe noch niedrige) beeinflussten die Ergebnisse.
Ich habe einen Teil der Wartezeit genutzt, um eine Kostenprognose zu erstellen: Die Durchführung dieses Experiments in drei Regionen kostet weniger als 0,04 $ pro Tag. Bei der Einrichtung dieses Experiments sind die Kosten für die (weniger als 5000 täglichen) Anfragen vernachlässigbar. Es sind vor allem die täglich 600 GB-Sekunden, die für die Ausführung benötigt werden, die zur Rechnung beitragen.
Die Ergebnisse
In der folgenden Tabelle finden Sie die Ergebnisse in Kurzform. In Experiment 1a (das zwei Tage lang lief) variierte die Verzögerung (in Minuten) zwischen den Anfragen an den AWS Lambda. In Experiment 1b (das ebenfalls zwei Tage lang lief) war die Verzögerung zwischen aufeinanderfolgenden Anfragen auf 4 Minuten festgelegt, aber die Speichergröße der Lambda-Instanz variierte.
In Experiment 2 (das eine Woche lang lief) variierte wiederum die Verzögerung (in Minuten) zwischen den Anfragen an die Lambda-Funktion. Im Wesentlichen handelte es sich um ein ähnliches Experiment wie unter 1a aufgeführt, nur dass es länger lief. Experiment 2 umfasste auch einen Durchlauf mit einer Verzögerung von etwa 10 Sekunden zwischen den Lambda-Aufrufen.
| Experiment 1a (für zwei Tage) | Verzögerung zwischen Anfragen (in Min.) | Größe des Instanzspeichers (in MB) | durchschnittliche Lebensdauer der Instanz (in Min.) | Standardabweichung der Lebensdauer der Instanz (in Min.) |
| us-ost-1 | 1 | 1024 | 124 | 31 |
| 2 | 1024 | 112 | 42 | |
| 3 | 1024 | 126 | 22 | |
| 5 | 1024 | 121 | 32 | |
| 10 | 1024 | 104 | 46 | |
| 15 | 1024 | - | - | |
| eu-west-1 | 1 | 1024 | 119 | 30 |
| 2 | 1024 | 135 | 8 | |
| 3 | 1024 | 120 | 35 | |
| 5 | 1024 | 115 | 30 | |
| 10 | 1024 | 129 | 21 | |
| 15 | 1024 | - | - | |
| ap-südost-1 | 1 | 1024 | 111 | 40 |
| 2 | 1024 | 119 | 35 | |
| 3 | 1024 | 116 | 40 | |
| 5 | 1024 | 110 | 38 | |
| 10 | 1024 | 116 | 39 | |
| 15 | 1024 | - | - | |
| Experiment 1b (zwei Tage lang) | ||||
| us-ost-1 | 4 | 256 | 124 | 26 |
| 4 | 512 | 113 | 42 | |
| 4 | 1024 | 116 | 36 | |
| 4 | 2048 | 111 | 38 | |
| eu-west-1 | 4 | 256 | 135 | 8 |
| 4 | 512 | 121 | 30 | |
| 4 | 1024 | 121 | 30 | |
| 4 | 2048 | 126 | 20 | |
| ap-südost-1 | 4 | 256 | 114 | 35 |
| 4 | 512 | 127 | 19 | |
| 4 | 1024 | 115 | 37 | |
| 4 | 2048 | 115 | 40 | |
| Experiment 2 (eine Woche lang) | ||||
| us-ost-1 | 1 | 1024 | 123 | 31 |
| 2 | 1024 | 121 | 32 | |
| 5 | 1024 | 119 | 33 | |
| eu-west-1 *) | 1 | 1024 | 127 *) | 22 |
| 2 | 1024 | 121 *) | 29 | |
| 5 | 1024 | 120 *) | 28 | |
| ap-südost-1 | 1 | 1024 | 124 | 30 |
| 2 | 1024 | 120 | 31 | |
| 5 | 1024 | 115 | 35 | |
| Experiment 2b (fünf Tage lang) | ||||
| eu-west-1 | Alle 10 Sekunden | 1024 | 113 | 37 |
*) Übrigens gab es während der Experimentwoche einen Zeitraum, in dem die Instanzen in eu-west-1 nicht alle zwei Stunden beendet wurden. Dies führte zu drei Instanzen, die 48 Stunden lang liefen. Diese außergewöhnlich langen Laufzeiten wurden bei der Berechnung der Durchschnittswerte und Standardabweichungen nicht berücksichtigt, da so etwas bei den anderen Experimenten nicht vorkam und auch nicht in den beiden anderen Regionen.
Als alternative Darstellung der Experimentdaten zeigt die untenstehende Grafik die tatsächlichen Lambda-Lebensdauern für eu-west-1 während des Experiments 2a.

Analyse
Wenn Sie sich die Ergebnisse des Experiments ansehen, werden einige Beobachtungen deutlich:
- Im Durchschnitt leben AWS Lambda-Instanzen etwa 130 Minuten, mit einer Standardabweichung von 30 Minuten. Der Wert der Standardabweichung wird stark von einigen Ausreißern beeinflusst, anstatt ein Symptom für ein allgemeines Muster mit einer großen Bandbreite an Lebenszeiten zu sein.
- Keine Instanz wird jemals 15 Minuten oder länger im Leerlauf betrieben. Passive Instanzen (die kaum Datenverkehr erhalten) werden präventiv beendet, wenn eine Funktion 15 Minuten lang nicht aufgerufen wird. Ich habe die 'garantierte Abschaltzeit' nicht gefunden, aber sie liegt irgendwo zwischen 10 und 15 Minuten Inaktivität.
- Während des Experiments 1 hatten die Instanzen in
eu-west-1eine etwas längere Lebensdauer als die Instanzen inus-east-1undap-southeast-1und eine geringere Variabilität der Lebensdauer. Zunächst schien es, als ob die Instanzen ineu-west-1in einer stabileren Umgebung operierten. Bei Experiment 2, das über einen längeren Zeitraum lief, verschwand dieser Effekt jedoch vollständig, und es konnte kein eindeutiger Zusammenhang zwischen der Region und der durchschnittlichen Lebensdauer der Instanzen festgestellt werden. - Es könnte ein kleiner Zusammenhang zwischen der Häufigkeit der Funktionsaufrufe und der Lebensdauer der Instanzen bestehen. Instanzen für Funktionen, die häufiger ausgeführt werden, scheinen eine etwas längere Lebensdauer zu haben als Funktionen, die seltener aufgerufen werden... außer bei Funktionen, die alle 10 Sekunden ausgeführt werden, die wiederum eine kürzere Lebensdauer aufweisen.
- Es gibt keine starke Korrelation zwischen der Größe des Instanzspeichers und der Lebensdauer. Instanzen mit 1024 MB hatten eine vergleichbare Lebensdauer wie Instanzen mit 256 MB, 512 MB, 1024 MB und 2048 MB.
Schlussfolgerungen
AWS Lambda beendet aktive Instanzen präemptiv und vorhersehbar alle 130 Minuten. Die Intensität des Datenverkehrs mit Lambda wirkt sich leicht auf die Lebensdauer aus: Aktivere Instanzen haben eine etwas längere Lebensdauer, aber die durchschnittliche Lebensdauer schwankt weniger als 10 Minuten. Auch die Größe des für die Instanz bereitgestellten Speichers und die Region (von den drei getesteten Regionen) haben einen signifikanten Einfluss auf die durchschnittliche Lebensdauer.
Um diese Entdeckung und die Experimente zu beenden: Ungeachtet aller Bemühungen, Kaltstarts zu verhindern, beendet AWS Lambda absichtlich laufende Lambda-Instanzen und erzwingt damit letztlich Kaltstarts. Das ist übrigens das gute Recht von AWS, aber eine Erkenntnis, die ich nicht dokumentiert oder beschrieben finden konnte.
Erwarten und planen Sie also nicht, dass Ihre Lambda-Instanzen lange Zeit laufen und mehrere Anfragen von derselben laufenden Instanz bedienen. Selbst ein kontinuierlicher Strom von Ereignissen oder Datenverkehr schützt Ihre AWS Lambda-Instanzen nicht davor, beendet zu werden.
[Bearbeiten: Nach der ursprünglichen Veröffentlichung wurde ein Streudiagramm hinzugefügt, das die tatsächlichen Lebenszeiten der Instanzen von eu-west-1 während des Experiments 2 zeigt, sowie die Beobachtung, dass die Standardabweichung der Lebenszeit wahrscheinlich erheblich durch zufällige Ausreißer beeinflusst wurde und nicht durch das Vorhandensein eines generischen Musters.]
Verfasst von
Jochem Schulenklopper
Unsere Ideen
Weitere Blogs
Contact



