اللاخوادم والعمليات المدفوعة بالأحداث

النموذج بلا خوادم

18 دقيقة الدرس 1 من 28

النموذج بلا خوادم

يُعدّ نموذج "بلا خوادم" الأكثر تسويقًا والأكثر سوء فهم في عالم الحوسبة السحابية. كثيرًا ما يستهين به المهندسون المتمرسون على Kubernetes باعتباره "مجرد Lambda" — أداة مناسبة فقط للنصوص البرمجية الصغيرة. في المقابل، يميل بعض المهندسين الذين لم يتعاملوا مع الحاويات إلى اعتباره بديلًا شاملًا لكل شيء. كلا الحكمين مغلوط. لتشغيل منصات بلا خوادم على نطاق إنتاج حقيقي، تحتاج إلى فهم دقيق لحقيقة هذا النموذج وما يفرضه من قيود وأين يقع على الطيف الممتد من الخوادم المعدنية إلى الخدمات المُدارة بالكامل.

ماذا تعني "بلا خوادم" فعلًا؟

الاسم مصطلح تسويقي. الخوادم موجودة بلا شك. الخاصية المميزة ليست غياب الخوادم — بل غياب إدارة الخوادم كمسؤولية تشغيلية عليك. بدقة أكبر، يصف هذا المصطلح نموذج فوترة وتنفيذ يرتكز على أربع خصائص جوهرية:

  • لا تخصيص مسبق للموارد: لا تحجز طاقة سلفًا. لا نوع حالة تختاره، ولا مجموعة تحجيم تضبطها، ولا تجمع عقد تحدد حجمه.
  • توسع تلقائي حتى الصفر: حين لا توجد طلبات، لا تدفع شيئًا. تتوسع الطاقة من الصفر إلى آلاف الاستدعاءات المتزامنة دون أي تدخل من المشغل.
  • فوترة لكل استدعاء: تدفع مقابل مدة تشغيل كودك، محسوبًا بالغيغابايت-ثانية (الذاكرة × الوقت الفعلي)، لا مقابل طاقة محجوزة.
  • بيئات تنفيذ مؤقتة: كل استدعاء يعمل في بيئة معزولة أُحادية الاستخدام. قد يُعاد استخدام وقت التشغيل (بدء دافئ)، لكن لا يمكنك الاعتماد على ذلك.

التطبيق الأبرز لنموذج FaaS هو AWS Lambda الذي أطلقته أمازون في نوفمبر 2014. تتبع Google Cloud Functions وAzure Functions المنطق ذاته. والنظائر المبنية على Kubernetes كـ Knative وOpenFaaS وKEDA تُطبق النموذج الاقتصادي نفسه على بنية حاويات تديرها أنت.

تمييز جوهري: "بلا خوادم" بوصفه نموذج فوترة وتنفيذ يختلف عن "بلا خوادم" بوصفه نمط معمارية. قد يجمع التطبيق الكامل العاري من الخوادم بين Lambda (الحساب) وAPI Gateway (HTTP) وDynamoDB (NoSQL) وSQS (قائمة انتظار) وS3 (التخزين) وEventBridge (ناقل الأحداث) — لا تدير أيًا منها على مستوى نظام التشغيل. النموذج يسري على المجموعة التقنية بأكملها، لا على طبقة الحساب وحدها.

اقتصاديات FaaS بالتفصيل

الحجة الاقتصادية لصالح FaaS مقنعة في أنماط حركة مرور بعينها، غير أن المهندسين كثيرًا ما يبالغون في تقديرها. نموذج التكلفة الفعلي لـ AWS Lambda كما هو في عام 2025:

  • الطلبات: 0.20 دولار لكل مليون استدعاء (أول مليون مجاني شهريًا)
  • المدة: 0.0000166667 دولار لكل غيغابايت-ثانية، تُحتسب بدقة المللي ثانية
  • التزامن المُوفَّر: 0.0000041667 دولار لكل غيغابايت-ثانية (حالات دافئة محجوزة — تُلغي بدايات التهيئة الباردة، وتُفوتر بشكل منفصل)

احسب التكلفة لدالة بذاكرة 256 ميغابايت ومتوسط وقت تشغيل 200 ملّي ثانية و10 ملايين استدعاء شهريًا:

# Lambda cost calculation (256 MB, 200ms avg, 10M invocations/month) Requests: 10,000,000 × $0.20 / 1,000,000 = $2.00 Duration: 10,000,000 × 0.256 GB × 0.2s = 512,000 GB-seconds 512,000 × $0.0000166667 = $8.53 Total: = $10.53/month # Equivalent EC2 (t3.small, 2 vCPU, 2GB RAM, us-east-1) On-demand: $0.0208/hr × 720 hrs = ~$15/month # Lambda يصبح مكلفًا عند تزامن مرتفع ومستدام: # 1,000 concurrent × 24hr × 30 days × $0.0000166667 × 0.256 GB × 1s = $3,686/month # مقابل 2× t3.xlarge ($0.1664/hr × 2 × 720 ساعة) = ~$240/month

نقطة التقاطع هي نحو 20–30% من استخدام المعالج بشكل مستدام طوال الشهر. دون هذه النسبة، يفوز نموذج FaaS من حيث التكلفة. فوقها، تكون الطاقة المحجوزة (EC2، ECS، Kubernetes) أرخص. معظم أنظمة الإنتاج التي تدرّ إيرادات تعمل فوق هذا المستوى — ولهذا لا تكون Lambda إجابة شاملة.

القيود الصارمة التي لا تُفاوَض عليها

تفرض Lambda حدودًا صارمة تُعدّ قرارات معمارية لا خيارات ضبط:

  • الحد الأقصى لوقت التنفيذ: 15 دقيقة لكل استدعاء. المهام طويلة الأمد (ETL، تدريب نماذج ML، ترميز الفيديو) تحتاج إلى تنسيق عبر Step Functions أو نموذج حساب مختلف كليًا.
  • الذاكرة: من 128 ميغابايت إلى 10,240 ميغابايت، قابلة للضبط بزيادات 1 ميغابايت. تُخصص وحدات المعالج بالتناسب — عند 1,769 ميغابايت تحصل على vCPU واحد بالضبط، وعند 10,240 ميغابايت تحصل على 6 وحدات.
  • القرص المؤقت: يوفر /tmp من 512 ميغابايت إلى 10,240 ميغابايت. لا شيء يبقى بين الاستدعاءات ما لم تكتبه إلى تخزين خارجي (S3، تحميل EFS، DynamoDB).
  • التزامن: الحد الافتراضي للحساب هو 1,000 استدعاء متزامن لكل منطقة. هذا حاجز صارم — الوصول إليه يعني استجابات 429 لمستخدميك. التزامن المحجوز يخصص شريحة، والتزامن المُوفَّر يُبقي الحالات دافئة.
  • حزمة النشر: 50 ميغابايت مضغوطة، 250 ميغابايت غير مضغوطة (مع الطبقات). نشر صور الحاويات يمدد هذا الحد إلى 10 غيغابايت.
  • الشبكة: الدوال داخل VPC تضيف تأخير بدء التهيئة (إرفاق ENI، كان تاريخيًا أكثر من 10 ثوانٍ — الآن أقل من ثانية مع hyperplane ENIs، لكنه لا يزال غير مهمل). الدوال خارج VPC لا تصل إلى الموارد الخاصة.
فخ إنتاجي — حدود التزامن تتسلسل: إذا استهلكت دالة Lambda واحدة حد تزامن حسابك بأكمله (مثل مهمة دفعية تستدعي 1,000 نسخة متزامنة)، ستُقيَّد كل دالة Lambda أخرى في تلك المنطقة إلى الصفر. اضبط دائمًا حد التزامن المحجوز لكل دالة على حدة. استخدم --reserved-concurrent-executions لتحديد سقف الدوال الدفعية وغير المتزامنة جيدًا دون حد الحساب، وراقب مقاييس CloudWatch لـ ConcurrencySpilloverInvocations وThrottles كمؤشرات SLI.

طيف نماذج النشر

لا يوجد نموذج "بلا خوادم" في فراغ. كل نموذج نشر يُقايض بين التحكم وعبء التشغيل. فهم موقع FaaS على هذا الطيف هو ما يُمكّن المهندسين الكبار من اتخاذ قرارات معمارية صائبة بدلًا من اتباع موجات الضجيج.

Deployment model spectrum: control vs. operational burden More Control Less Ops Burden Bare Metal OS, kernel, drivers: yours Full control VMs / EC2 Hypervisor managed for you OS: yours Containers ECS / K8s Runtime managed; image: yours PaaS App Engine Run Engine / Fly App code: yours FaaS Lambda / GCF Event handler Function: yours Your responsibility at each tier: Bare Metal: hardware + firmware + OS + runtime + app + data + scaling + HA EC2: OS + runtime + app + data + scaling + HA Containers: image + app + data (scaling/HA: shared) FaaS: function + data
طيف نماذج النشر — من المعدن المكشوف (تحكم كامل، أعلى عبء تشغيلي) إلى FaaS (أقصى درجات التجريد، أصغر سطح تديره أنت).

متى يناسب النموذج بلا خوادم — ومتى لا يناسب

القرار الذي يميز المهندس الكبير هو التعرف على أنماط الأعباء التي تبرع فيها FaaS مقابل التي ستعاني منها. هذا ليس مسألة تفضيل — لكل نمط سبب اقتصادي وتشغيلي قابل للإثبات:

مناسب جدًا لـ FaaS:

  • حركة مرور متذبذبة وغير قابلة للتنبؤ: webhook للدفع يُطلق صفر مرات الساعة الثالثة صباحًا، ثم 50,000 مرة خلال تخفيض مفاجئ. لا طاقة محجوزة مسبقًا، ولا تأخر في التحجيم التلقائي، ولا تكلفة وقت الخمول.
  • خطوط أنابيب مدفوعة بالأحداث: رفع S3 ← تصغير صورة ← كتابة DynamoDB ← إشعار SQS. كل خطوة دالة منفصلة. عزل الأعطال والتحجيم المستقل ودلالات إعادة المحاولة مدمجة.
  • مهام جدولة ذات تردد منخفض: توليد تقرير ليلي، تصدير بيانات يومي. Lambda المُشغَّلة بـ Cron أرخص بكثير وأبسط من حالة EC2 مخصصة تعمل خاملة 23.5 ساعة يوميًا.
  • كود الربط وتحويل البيانات: خطوات ETL، تحويل الصيغ، إرسال إشعارات موزعة. مدة قصيرة، لا حالة، إمكانية تزامن عالية — الحمل المثالي لـ Lambda.
  • خلفية للتطبيقات المحمولة وإنترنت الأشياء بحجم متغير: API Gateway + Lambda يتعاملان مع الصفر إلى الملايين دون تدخل من المشغل. على الحجم المنخفض إلى المتوسط، الاقتصاديات مقنعة.

غير مناسب لـ FaaS:

  • APIs متزامنة عالية RPS وحساسة للتأخير: بدايات التهيئة الباردة (50 ملّي ثانية إلى أكثر من ثانية حسب وقت التشغيل وحجم الحزمة) غير مقبولة لـ SLO تحت 100 ملّي ثانية. التزامن المُوفَّر يُخفف هذا لكنه يُلغي ميزة التكلفة.
  • الحساب طويل الأمد: أي شيء يقترب من 15 دقيقة أو يتجاوزها (خطوط أنابيب ML، ترميز الفيديو، ضمات البيانات الكبيرة) يحتاج إلى ECS Fargate أو SageMaker أو Kubernetes.
  • معدل نقل مرتفع ومستدام: إذا كنت تحتاج إلى أكثر من 500 استدعاء متزامن على مدار الساعة طوال اليوم، فنموذج الفوترة لكل استدعاء أغلى من الطاقة المحجوزة في EC2 أو ECS. احسب الأرقام قبل الالتزام.
  • أعباء العمل ذات الحالة أو المتدفقة: مستهلكو Kafka، خلفيات WebSocket، اتصالات قاعدة بيانات طويلة الأمد — هذه الأنماط تتعارض مع نموذج Lambda المؤقت عديم الحالة. استخدم ECS أو EKS.
  • تبعيات معقدة: الدوال التي تتطلب مكتبات أصلية كبيرة (أكثر من 250 ميغابايت غير مضغوطة)، أو وصولًا إلى GPU، أو ميزات نواة محددة لا تعمل في Lambda. استخدم Lambda المبنية على الحاويات أو طبقة حساب مختلفة.
ممارسة إنتاجية — قاعدة الدقيقتين: إذا لم يستطع مهندس في شركة من الدرجة الأولى وصف مشغّل دالة Lambda، ومتوسط مدتها p99، ونمط فشلها، وكيفية تحجيمها في دقيقتين — فالدالة ليست جاهزة للإنتاج. بساطة Lambda فخ — تجعل من السهل نشر كود لا رؤية له، ولا قائمة انتظار للرسائل الفاشلة، ولا سقف للتزامن، ولا ميزانية للتقييد. يجب أن يكون الانضباط التشغيلي أعلى من الحاويات، لا أدنى، لأن نطاق تأثير الدالة المتصرفة بشكل خاطئ هو تجمع تزامن الحساب بأكمله.

بيئات التشغيل ونماذج التنفيذ

تدعم Lambda بيئات تشغيل مُدارة (Node.js 20/22، Python 3.12/3.13، Java 21، .NET 8، Ruby 3.3) وبيئات مخصصة عبر provided.al2023 (تُستخدم مع Go وRust وأي ثنائي ينفذ Lambda Runtime API). اعتبارًا من عام 2025، تعمل جميع بيئات التشغيل المُدارة الجديدة على Amazon Linux 2023 — بيئات AL1 وAL2 مُهجَّرة ولا ينبغي استخدامها في الدوال الجديدة.

نموذج التنفيذ مهم لأداء بدء التهيئة البارد. Python وNode.js لديهما بدايات باردة أقل من 100 ملّي ثانية في أحجام الحزم الصغيرة. Java مع Spring Boot قد يتجاوز 3 ثوانٍ. تجميع GraalVM الأصلي وQuarkus يُخفضان بدايات Java الباردة إلى أقل من 200 ملّي ثانية. Rust على provided.al2023 يبدأ باستمرار في 10–30 ملّي ثانية. اختيار بيئة التشغيل قرار تشغيلي له تداعيات مباشرة على SLO.

# Deploy a minimal Lambda function with AWS SAM (2025 pattern) # template.yaml AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Globals: Function: Runtime: python3.13 Architectures: [arm64] # Graviton2 — أرخص 20%، نفس الأداء MemorySize: 256 Timeout: 30 Environment: Variables: LOG_LEVEL: INFO POWERTOOLS_SERVICE_NAME: payment-processor Resources: PaymentProcessor: Type: AWS::Serverless::Function Properties: Handler: handler.lambda_handler ReservedConcurrentExecutions: 200 # لا تستهلك تجمع التزامن الكامل AutoPublishAlias: live DeploymentPreference: Type: Canary10Percent5Minutes # نقل 10% من الحركة، مراقبة 5 دقائق ProvisionedConcurrencyConfig: ProvisionedConcurrentExecutions: 5 # إبقاء 5 حالات دافئة لـ p99 Events: ApiEvent: Type: Api Properties: Path: /payments Method: post Policies: - DynamoDBCrudPolicy: TableName: !Ref PaymentsTable DeadLetterQueue: Type: SQS TargetArn: !GetAtt PaymentsDLQ.Arn PaymentsDLQ: Type: AWS::SQS::Queue Properties: MessageRetentionPeriod: 1209600 # 14 يومًا # النشر sam build --use-container sam deploy --guided

تحول عقلية التشغيل

يحمل المهندسون القادمون من Kubernetes نموذجًا ذهنيًا للعمليات طويلة الأمد: حاويات تبدأ مرة واحدة وتسخّن تجمعات الاتصالات وتُعبئ ذاكرة التخزين المؤقت وتعالج آلاف الطلبات قبل الاستبدال. Lambda يقلب هذا النموذج رأسًا على عقب. دالتك هي معالج طلبات، لا عملية. الكود الموجود خارج المعالج يعمل مرة واحدة لكل بيئة تنفيذ (استخدمه لإنشاء اتصالات DB وتحميل الإعدادات من SSM Parameter Store)، لكن عليك تصميم كل دالة على افتراض أن البيئة ستُتلف بعد كل استدعاء — لأنها قد تكون كذلك فعلًا.

يؤثر هذا التحول على كل قرار معماري لاحق: كيف تدير الحالة (أخرجها إلى الخارج — DynamoDB وElastiCache وS3)، وكيف تتعامل مع التزامن (كل استدعاء مستقل — لا أقفال مشتركة داخل العملية)، وكيف تراقب السلوك (التتبع لا السجلات وحدها — الطلب يمتد عبر استدعاءات Lambda متعددة)، وكيف تتعامل مع الأعطال (قوائم الرسائل الفاشلة ومفاتيح الأيدمبوتنسية ودلالات التسليم مرة واحدة على الأقل من كل مصدر أحداث). تبني الدروس التالية في هذا البرنامج كل واحدة من هذه المخاوف التشغيلية بعمق.