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

مصادر الأحداث والمشغّلات

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

مصادر الأحداث والمشغّلات

دالة Lambda في حالة خمول تام حتى يُستدعى تنفيذها. تُصنِّف AWS نماذج الاستدعاء في ثلاثة أنواع: متزامن (API Gateway وALB ومشغّلات Cognito)، وغير متزامن (أحداث S3 وSNS وEventBridge)، واستطلاع تدفقي (SQS وKinesis وDynamoDB Streams). يختلف كل نموذج في دلالات إعادة المحاولة ومعالجة الأخطاء وسلوك ضغط الظهر. اختيار النموذج الخاطئ هو الجذر الأساسي لمعظم أخطاء الإنتاج في الأنظمة المدفوعة بالأحداث.

API Gateway — نقطة الدخول HTTP المتزامنة

يُعدّ API Gateway (HTTP API v2 أو REST API v1) المشغِّل المتزامن السائد. يظل المُستدعي محجوبًا في انتظار الرد؛ وبالتالي يصبح حدّ التزامن في Lambda هو سقف الإنتاجية لخدمتك مباشرةً. تُضيف HTTP API v2 زمن استجابة لا يتجاوز 1–2 مللي ثانية، في حين تُضيف REST API قرابة 5–10 مللي ثانية لقوالب التعيين والمُفوِّضين.

قواعد عملية على نطاق واسع: عيِّن Reserved Concurrency لكل دالة حتى لا تستنزف طفرات حركة المرور الحدود المشتركة للحساب (الافتراضي 1,000 لكل منطقة، حدّ مرن). استخدم provisionedConcurrencyConfig للقضاء على البدايات الباردة في المسارات الحيوية. فعِّل ضغط الحمولة (minimumCompressionSize: 1024) وتخزين الاستجابات المؤقت لنقاط نهاية GET. ربِّط مُفوِّض Lambda (JWT أو IAM) بدلًا من إجراء التحقق داخل الدالة — إذ يُخزَّن مؤقتًا وفق TTL ويُبقي منطق العمل نظيفًا.

# إطار Serverless Framework — مشغّل HTTP API v2 مع مُفوِّض وتزامن مُحجوز functions: orderApi: handler: src/orders.handler reservedConcurrency: 500 provisionedConcurrencyConfig: provisionedConcurrentExecutions: 10 events: - httpApi: path: /orders/{orderId} method: GET authorizer: name: jwtAuthorizer identitySource: $request.header.Authorization jwtAuthorizer: handler: src/auth.handler
يمتلك API Gateway مهلة تكامل صارمة مدتها 29 ثانية. إذا تجاوز تنفيذ Lambda ذلك، يتلقى العميل خطأ 504 حتى وإن كانت الدالة لا تزال تعمل. للمهام طويلة التنفيذ، أعِد استجابة 202 فورًا وادفع العمل إلى SQS أو Step Functions.

SQS — فصل غير متزامن مع ضبط ضغط الظهر

يُعدّ SQS من أكثر مشغّلات Lambda متانةً تشغيليًا. يتدرّج مستطلع Lambda الداخلي من 5 دفعات متزامنة حتى 1,000 (طوابير Standard) أو 300 × عدد الأقسام (FIFO). أهم المعاملات ذات الأثر في الإنتاج:

  • BatchSize (من 1 إلى 10,000): الدُّفعات الأكبر تعني إنتاجية أعلى لكن زمن استجابة أطول لكل عنصر. لعمليات معالجة قواعد البيانات، يكون 100–500 هو النطاق النموذجي.
  • MaximumBatchingWindowInSeconds (من 0 إلى 300): ينتظر Lambda هذه المدة لملء دفعة قبل الاستدعاء. يُقلّل الاستدعاءات على حساب زمن الاستجابة؛ اضبطه على 0 للأنابيب الآنية.
  • FunctionResponseTypes: [ReportBatchItemFailures]: أكثر إعداد مؤثّر في SQS. بدونه، يؤدي فشل عنصر واحد في دفعة إلى إعادة جميع العناصر إلى الطابور مما يُسبّب تكرارًا. بتفعيله، تُعيد الدالة مصفوفة batchItemFailures وتُعاد فقط العناصر الفاشلة إلى الطابور.
  • طابور الرسائل الميتة (DLQ): أرفقه بطابور SQS (لا بالدالة) كي تستقر الرسائل التي استنفدت maxReceiveCount في مكان معروف للتحليل.
# CloudFormation / SAM — مشغّل SQS مع الإبلاغ عن فشل جزئي للدفعة OrderProcessorFunction: Type: AWS::Serverless::Function Properties: Handler: src/processor.handler Events: SQSTrigger: Type: SQS Properties: Queue: !GetAtt OrderQueue.Arn BatchSize: 100 MaximumBatchingWindowInSeconds: 5 FunctionResponseTypes: - ReportBatchItemFailures OrderQueue: Type: AWS::SQS::Queue Properties: VisibilityTimeout: 360 # 6 أضعاف مهلة الدالة RedrivePolicy: deadLetterTargetArn: !GetAtt OrderDLQ.Arn maxReceiveCount: 3 OrderDLQ: Type: AWS::SQS::Queue
اضبط VisibilityTimeout في SQS على ما لا يقل عن 6 أضعاف مهلة Lambda. إذا انتهت مهلة الدالة عند 60 ثانية لكن مهلة الرؤية 30 ثانية، تصبح الرسالة مرئية مجددًا بينما الدالة لا تزال تعمل — ما يُفضي إلى استدعاء مكرر في منتصف التنفيذ.

EventBridge — حافلة الأحداث والقواعد المجدولة

يُعدّ EventBridge (المعروف سابقًا بـCloudWatch Events) موجِّه الأحداث في AWS. يقع في مركز معظم بنى الأحداث لأنه يفصل المنتجين عن المستهلكين كليًا — يُرسل المنتج حدث JSON منظَّم إلى حافلة؛ تُرشِّح القواعد وتُوزِّع على الأهداف (Lambda وSQS وSNS وStep Functions وAPI destinations وحتى حافلات عبر الحسابات). تتلقى حافلة الأحداث الافتراضية أحداث خدمات AWS؛ أما الحافلات المخصصة فهي الممارسة المُثلى لأحداث التطبيقات.

EventBridge غير متزامن بطبيعته: تتلقى Lambda الحدث ولا ينتظر EventBridge الرد. إعادة المحاولة قابلة للضبط لكل هدف (من 0 إلى 185) مع تراجع أسي يصل حتى 24 ساعة. أرفق DLQ على قاعدة هدف EventBridge، لا على الدالة وحدها، لالتقاط الأحداث التي فشلت قبل أن تُستدعى Lambda أصلًا.

يتيح Schema Registry توليد ارتباطات مكتوبة تلقائيًا من مخططات أحداثك — أمر بالغ الأهمية للفرق الكبيرة لتجنب انجراف المخطط الصامت. فعِّله على حافلتك المخصصة وضع إصدارًا لمخططاتك عبر بيانات وصفية SchemaVersion في كل حدث.

Event Sources flowing into Lambda via different integration models Synchronous API Gateway (HTTP/REST) ALB / Function URL Asynchronous S3 Events EventBridge SNS Poll-Based (SQS / Kinesis) Lambda Function Concurrency DynamoDB / RDS SQS (fan-out) EventBridge Bus S3 / Step Functions invocation model determines retry, ordering, and back-pressure behaviour
ثلاثة نماذج لاستدعاء Lambda: متزامن (يُعيق المُستدعي)، غير متزامن (أطلق وانسَ مع إعادة محاولة)، واستطلاع قائم (Lambda تُدير الاستطلاع وضغط الظهر).

أحداث S3 — إشعارات مستوى الكائن

تُسلَّم إشعارات أحداث S3 (s3:ObjectCreated:* وs3:ObjectRemoved:* وغيرها) بصورة غير متزامنة. كل إشعار عبارة عن حمولة JSON تصف الدلو والمفتاح والحجم وETag. نقاط عملية تُعاني منها الفرق في الإنتاج:

  • التسليم مرة واحدة على الأقل: أحداث S3 ليست بالضبط مرة واحدة. تحت معدلات إنشاء كائنات مرتفعة جدًا يمكن استلام إشعارات مكررة للكائن نفسه. صمِّم معالجك ليكون معطوف النتيجة (idempotent) — مثلًا: اكتب علامة معالجة في DynamoDB بتعبير شرطي قبل القيام بالعمل المُكلف.
  • لا ضمان تسليم للكائنات الصغيرة جدًا: عمليات الكتابة المتقاربة جدًا على المفتاح ذاته قد تتدمج في إشعار واحد. استخدم توصيل أحداث EventBridge من S3 (المسار الأحدث) إذا احتجت إلى دقة أعلى — فهو يمر عبر حافلة الأحداث مع دعم إعادة المحاولة وDLQ.
  • تصفية الأحداث: أضف فلاتر بادئة/لاحقة على إعداد الإشعار لتجنب استدعاء دالتك على مخرجاتها (خطأ الحلقة اللانهائية الكلاسيكي: الدالة تقرأ من raw/ وتكتب إلى processed/ لكن الإشعار يغطي كل المفاتيح).
# Terraform — إشعار S3 إلى Lambda مع فلتر البادئة والبديل عبر EventBridge resource "aws_s3_bucket_notification" "uploads" { bucket = aws_s3_bucket.uploads.id lambda_function { lambda_function_arn = aws_lambda_function.processor.arn events = ["s3:ObjectCreated:*"] filter_prefix = "raw/" # استدعاء فقط عند تحميلات raw/ filter_suffix = ".json" } } # منح S3 صلاحية استدعاء Lambda resource "aws_lambda_permission" "s3_invoke" { statement_id = "AllowS3Invoke" action = "lambda:InvokeFunction" function_name = aws_lambda_function.processor.function_name principal = "s3.amazonaws.com" source_arn = aws_s3_bucket.uploads.arn } # --- المفضّل للإنتاج: التوجيه عبر EventBridge لإعادة المحاولة + DLQ --- resource "aws_s3_bucket_notification" "uploads_eb" { bucket = aws_s3_bucket.uploads.id eventbridge = true # كل الأحداث تذهب إلى الحافلة الافتراضية }

قواعد EventBridge — التصفية والتوزيع

تطابق قواعد EventBridge الأحداث باستخدام تصفية قائمة على المحتوى — يمكنك الفلترة على أي حقل في JSON بما في ذلك الحقول المتداخلة والمصفوفات. مخطط حدث جيد البنية مع detail-type وsource مكتوبَيْن يُقلّل تعقيد القواعد بشكل كبير عبر شبكة خدمات ضخمة.

# AWS CLI — قاعدة تطابق أحداث OrderPlaced بأكثر من 1000 دولار aws events put-rule \ --name "HighValueOrders" \ --event-bus-name "orders-bus" \ --event-pattern '{ "source": ["com.acme.orders"], "detail-type": ["OrderPlaced"], "detail": { "amount": [{"numeric": [">", 1000]}], "currency": ["USD"] } }' \ --state ENABLED # إضافة هدف Lambda مع إعادة محاولة وDLQ aws events put-targets \ --rule "HighValueOrders" \ --event-bus-name "orders-bus" \ --targets '[{ "Id": "fraud-check", "Arn": "arn:aws:lambda:us-east-1:123456789012:function:FraudCheck", "RetryPolicy": {"MaximumRetryAttempts": 3, "MaximumEventAgeInSeconds": 3600}, "DeadLetterConfig": {"Arn": "arn:aws:sqs:us-east-1:123456789012:HighValueDLQ"} }]'
الإنتاجية الافتراضية لـEventBridge هي 10,000 حدث/ثانية لكل حافلة لكل منطقة (حدّ مرن قابل للرفع). عند هذا النطاق، التوزيع على مئات من أهداف Lambda أمر اعتيادي. تتيح حافلات الأحداث عبر الحسابات والمناطق بناء شبكة أحداث على مستوى المؤسسة بلوحة تحكم واحدة — النمط الذي تستخدمه خدمات Amazon الداخلية.

اختيار المشغِّل المناسب

يُأطِّر المهندسون المتقدمون اختيار المشغِّل حول أربعة محاور: تحمُّل زمن الاستجابة، ومتطلبات الترتيب، وضغط الظهر، ورؤية الفشل. API Gateway حين يحتاج المُستدعي إلى إجابة فورية. SQS حين تحتاج إلى قوائم انتظار متينة وضغط ظهر ومعالجة فشل جزئي للدفعة. EventBridge حين تحتاج إلى توجيه قائم على المحتوى عبر الخدمات والحسابات. أحداث S3 (عبر EventBridge) حين يكون المشغِّل دورة حياة كائن. Kinesis Data Streams حين تحتاج إلى تدفق مرتَّب قابل للإعادة وعالي الإنتاجية.

نمط مضادّ يتكرر في الإنتاج: سلسلة استدعاءات Lambda المتزامنة (lambda.invoke من داخل دالة). هذا يُقرِّن زمن الاستجابة ويستهلك التزامن مضاعفًا ويُخفي الأعطال. استبدل كل سلسلة متزامنة بـSQS أو EventBridge — يُرسل المُستدعي، يستطلع المُستقبل، ويتدرّج كلاهما ويفشل باستقلالية تامة.