Einleitung: Warum Rust für Serverless ein Durchbruch ist
\n\nDie Serverless-Architektur ist bereits seit langem der Standard für den Aufbau skalierbarer und kosteneffizienter Anwendungen. Die traditionelle Wahl der Sprachen (Python, Node.js, Java) stößt jedoch häufig auf Probleme mit dem Kaltstart und einem hohen Speicherverbrauch. Rust bietet mit seinen kostenlosen Abstraktionen und dem Fehlen eines Garbage Collectors eine revolutionäre Lösung. In diesem Artikel werden wir uns ansehen, wie man Serverless-Funktionen in Rust für AWS Lambda erstellt, konfiguriert und deployed – von der Installation der Tools bis hin zu Production-Releases.
\n\nAm Ende dieses Artikels werden Sie in der Lage sein:
\n- \n
- Die Entwicklungsumgebung für Rust + AWS Lambda einzurichten \n
- Eine effiziente Funktion mit Ereignisverarbeitung zu schreiben \n
- Die Binärdatei für eine minimale Kaltstartzeit zu optimieren \n
- Die Funktion mit Cargo Lambda in AWS bereitzustellen \n
Umgebungsvorbereitung: Cargo Lambda und AWS CLI
\n\nFür die Arbeit mit Rust auf AWS Lambda benötigen wir ein spezielles Tool – cargo-lambda. Es automatisiert Build, Test und Deployment. Installieren wir es über Cargo:
cargo install cargo-lambda\n\nStellen Sie außerdem sicher, dass aws-cli (mit IAM-Schlüsseln konfiguriert) und Docker (für lokale Tests) installiert sind. Erstellen wir ein neues Projekt:
cargo lambda new my-rust-lambda\ncd my-rust-lambda\n\nDer Befehl erstellt eine grundlegende Struktur mit der Datei Cargo.toml und src/main.rs. Beachten Sie die Abhängigkeiten in Cargo.toml:
[package]\nname = "my-rust-lambda"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\nlambda_runtime = "0.11"\ntokio = { version = "1", features = ["macros", "rt-multi-thread"] }\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\ntracing = { version = "0.1", features = ["log"] }\ntracing-subscriber = { version = "0.3", features = ["fmt"] }\n\nDie Schlüsselbibliothek ist lambda_runtime. Sie stellt das Trait LambdaHandler bereit, das wir implementieren werden.
Schreiben der ersten Funktion: Verarbeitung einer API Gateway-Anfrage
\n\nBetrachten wir ein klassisches Szenario: eine Funktion, die einen JSON mit einem Benutzernamen empfängt und eine Begrüßung zurückgibt. Öffnen wir src/main.rs und schreiben den folgenden Code:
use lambda_runtime::{run, service_fn, Error, LambdaEvent};\nuse serde::{Deserialize, Serialize};\n\n#[derive(Deserialize)]\nstruct Request {\n name: String,\n}\n\n#[derive(Serialize)]\nstruct Response {\n message: String,\n}\n\nasync fn function_handler(event: LambdaEvent<Request>) -> Result<Response, Error> {\n let name = event.payload.name;\n let message = format!("Hallo, {}! Du hast gerade Rust auf Lambda gestartet!", name);\n Ok(Response { message })\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), Error> {\n tracing_subscriber::fmt()\n .with_max_level(tracing::Level::INFO)\n .init();\n\n run(service_fn(function_handler)).await\n}\n\nLassen Sie uns die wichtigsten Punkte erläutern:
\n- \n
LambdaEvent<Request>– eine Struktur, die den Anfragetext und den Ausführungskontext enthält. \n #[tokio::main]– die asynchrone Laufzeitumgebung, die für die Arbeit mit der Lambda-Laufzeit erforderlich ist. \n serde– Deserialisierung des eingehenden JSON und Serialisierung der Antwort. \n
Testen wir lokal:
\n\ncargo lambda watch\n\nDann in einem anderen Terminal:
\n\ncargo lambda invoke --data-ascii '{"name": "Alexej"}'\n\nSie sollten Folgendes sehen: {"message":"Hallo, Alexej! Du hast gerade Rust auf Lambda gestartet!"}
Optimierung des Kaltstarts und der Binärgröße
\n\nDer Hauptvorteil von Rust ist der minimale Kaltstart. Um dies zu erreichen, muss die Binärdatei jedoch richtig erstellt werden. Bi