
Ich habe etwas, das ich einen „Mikroservice“ nennen werde und das auf AWS Lambda (unter Verwendung von node.js) läuft.
Im Grunde liefert es komprimierte Zusammenfassungen, die aus einigen hundert Megabyte binärer Blobs stammen. Es gibt viele mögliche Ausgaben und das Vorabgenerieren aller Möglichkeiten ist keine Option. Außerdem muss es einigermaßen reaktionsschnell sein (im schlimmsten Fall etwa in weniger als einer Sekunde), da es (über API Gateway) von interaktiven Webseiten aus aufgerufen wird, die eine schnelle Änderung der Parameter ermöglichen. Die Zugriffsmuster im Blob sind im Wesentlichen zufällig, obwohl jede erstellte Zusammenfassung normalerweise nur auf ca. 0,1–1 % der Gesamtdaten zugegriffen hat. Die Daten und Zugriffsmuster sind nicht sehr kompatibel mit der Speicherung der Daten in einer Datenbank (siehe jedoch unten die Erwähnung von DynamoDB).
Mein aktueller Ansatz besteht darin, den großen Binärblob auf S3 zu hosten und die Lambda-Handler den Blob lokal zwischen Lambda-Aufrufen zwischenspeichern zu lassen (nur als Puffer im JavaScript-Code, mit Gültigkeitsbereich außerhalb der Handler-Funktion; offensichtlich ist der Speicher des Lambda ausreichend groß konfiguriert). Handler-Instanzen scheinen persistent genug zu sein, sodass ein Server, sobald er einmal betriebsbereit ist, gut funktioniert und sehr reaktionsschnell ist. Es gibt jedoch mindestens ein paar Nachteile:
Der erste Abruf der Daten von S3 scheint bei etwa 50–60 MByte/s zu liegen (was mit anderen Berichten zur S3-Bandbreite übereinzustimmen scheint, die ich gesehen habe), sodass es beim ersten Zugriff zu einer störenden Verzögerung von mehreren Sekunden kommen kann.
Im Zusammenhang mit dem vorherigen Punkt gilt: Wenn der Client sehr aktiv ist und/oder die Benutzerlast zunimmt, werden mehr Serverinstanzen gestartet und die Anfragen der Benutzer werden möglicherweise an Instanzen weitergeleitet, die beim Abrufen des Datenblobs ins Stocken geraten sind. Dies führt zu störenden Störungen in einem ansonsten reibungslos funktionierenden Client.
Ich gebe zu, dass ich wahrscheinlich zu viel von einem Dienst erwarte, der eigentlich als „zustandsloser“ Dienst gedacht ist, da er tatsächlich einen großen Teil des Zustands enthält (den Binärblob), aber ich frage mich, ob sich die Situation verbessern lässt. Beachten Sie, dass die Daten nicht besonders komprimierbar sind (es könnte möglich sein, 1/3 davon zu reduzieren, aber das ist nicht die Größenordnung, nach der ich suche, oder zumindest ist es bestenfalls nur ein Teil der Lösung).
Irgendwelche Vorschläge, wie man die Daten schneller ins Lambda bekommt? Ich stelle mir so etwas vor:
Ziehen Sie Ihre Daten von einem anderen Ort, wo Lambdas eine viel höhere Bandbreite haben ... aber was? DynamoDB (aufgeteilt in so viele 400.000-Binärdatensätze wie nötig)? ElastiCache? Etwas anderes im AWS-„Menü“, das mir nicht aufgefallen ist.
Verwenden Sie einen raffinierten Trick (was?), um Lambda-Instanzen „vorzuwärmen“.
Sie verwenden für diese Aufgabe völlig das falsche Werkzeug. Verwenden Sie stattdessen ...? (Das Lambda-Modell gefällt mir allerdings sehr gut. Sie müssen sich nicht um die Bereitstellung von Instanzen und die automatische Skalierung kümmern, sondern können sich ganz auf die Funktionalität konzentrieren.)
Wenn die kürzlich angekündigten Lambda-ähnlichen Angebote von Google oder Microsoft (über die ich wenig weiß) über irgendwelche Eigenschaften verfügen, die bei diesem Anwendungsfall hilfreich sein könnten, wäre das ebenfalls eine sehr interessante Information.
Eine Option, die ich in Betracht gezogen habe, besteht darin, die Binärdaten in ein „Bereitstellungspaket“ zu integrieren, aber die dafür geltende Grenze von 250 MB ist für einige vorgesehene Anwendungsfälle zu niedrig (selbst wenn der Blob komprimiert wäre).
Antwort1
Wenn der Binärblob nur ein paar hundert Megabyte groß ist, können Sie ihn einfach als „Abhängigkeit“ in Ihre Funktion einbinden. Sie können ihn als Datei neben Ihrem Code hinzufügen und entsprechend darauf verweisen.
Eine andere Möglichkeit wäre, zwei Lambda-Funktionen zu haben. Eine Funktion tut nichts anderes, als den Blob bereitzustellen (den Sie wie oben beschrieben erstellen, indem Sie den Blob mit der Funktion senden), und dann können Sie einen Timer (im Grunde Cron) verwenden, um diese Funktion jede Minute zu „kitzeln“, damit sie aktiv bleibt. Dann ist Ihr zweites Lambda dasjenige, das die Arbeit erledigt, und das erste, was es beim Start tut, ist, das erste Lambda aufzurufen, um den Blob abzurufen. Lambda-zu-Lambda-Aufrufe haben eine hohe Bandbreite, sodass die Startzeit kein Problem sein sollte.
Die ideale Lösung wäre, eine Möglichkeit zu finden, die Daten zusammenzufassen und in DynamoDB zu speichern, aber es hört sich so an, als hätten Sie diesen Weg ausprobiert, und er hat für Sie keinen Sinn ergeben.