وظائف Serverless بلغة Rust: AWS Lambda – أداء بدون خادم
أصبحت بنية Serverless معيارًا لبناء تطبيقات قابلة للتوسع وفعالة من حيث التكلفة. ومع ذلك، تواجه اللغات التقليدية لـ AWS Lambda (Python، Node.js، Java) مشكلة البدء البارد واستهلاك الذاكرة العالي. تقدم Rust، مع تجريداتها منخفضة التكلفة وتجميعها إلى كود أصلي، حلاً ثوريًا: وظائف تبدأ خلال ميلي ثانية وتستهلك الحد الأدنى من الموارد. في هذه المقالة، سنشرح كيفية إنشاء وظائف Serverless بلغة Rust لـ AWS Lambda، وإعداد البيئة، وتحسين الأداء.
لماذا Rust لـ Serverless؟
يعود اختيار Rust لـ AWS Lambda إلى ثلاثة عوامل رئيسية:
- البدء البارد الأدنى: لا يتطلب الملف الثنائي لـ Rust آلة افتراضية أو مفسرًا. وقت البدء هو 50–200 مللي ثانية مقابل 1–3 ثوانٍ لـ Python أو Java.
- استهلاك منخفض للذاكرة: تشغل وظائف Rust 5–15 ميجابايت من RAM، مما يسمح بتوفير تكلفة التنفيذ.
- أمان الذاكرة: نظام الملكية (ownership) يمنع تسرب الذاكرة وسباقات البيانات، وهو أمر بالغ الأهمية لأحمال الإنتاج.
Rust مثالية للمهام الحساسة لزمن الاستجابة: معالجة طلبات API، عمليات ETL، التحليلات في الوقت الفعلي.
إعداد المشروع والأدوات
للتطوير، ستحتاج إلى:
- Rust (التثبيت عبر
rustup) - أداة
cargo lambda(التثبيت:cargo install cargo-lambda) - حساب AWS و AWS CLI مُعد
أنشئ مشروعًا جديدًا:
cargo lambda new my-rust-functioncd my-rust-functionسيتم إنشاء هيكل مع ملف src/main.rs و Cargo.toml مع التبعيات الضرورية:
[package]name = "my-rust-function"version = "0.1.0"edition = "2021"
[dependencies]lambda_runtime = "0.11"serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"tokio = { version = "1", features = ["macros"] }tracing = "0.1"tracing-subscriber = { version = "0.3", features = ["fmt"] }التبعية الرئيسية هي lambda_runtime، والتي توفر بيئة تشغيل للتفاعل مع AWS Lambda.
كتابة أول وظيفة Serverless بلغة Rust
لننظر إلى مثال بسيط: دالة تستقبل JSON باسم وترجع تحية.
محتويات src/main.rs:
use lambda_runtime::{service_fn, LambdaEvent, Error};use serde::{Deserialize, Serialize};
#[derive(Deserialize)]struct Request { name: String,}
#[derive(Serialize)]struct Response { message: String,}
#[tracing::instrument(skip(event), fields(request_id = %event.context.request_id))]async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> { let request = event.payload; let message = format!("مرحبًا، {}! لقد استدعيت دالة Rust.", request.name); Ok(Response { message })}
#[tokio::main]async fn main() -> Result<(), Error> { tracing_subscriber::fmt() .with_max_level(tracing::Level::INFO) .init();
let func = service_fn(handler); lambda_runtime::run(func).await}تحليل الكود:
LambdaEvent— غلاف يحتوي على الحمولة وسياق التنفيذ.#[tracing::instrument]— تسجيل تلقائي مع معرف الطلب.service_fn— يكيّف المعالج غير المتزامن لبيئة Lambda runtime.
قم ببناء وتشغيل محليًا:
cargo lambda build --releasecargo lambda invoke --data-ascii '{"name": "العالم"}'الإخراج: {"message":"مرحبًا، العالم! لقد استدعيت دالة Rust."}