مختبر: استكشاف أخطاء Lambda
الهدف
تشخيص وتصحيح وظائف Lambda الفاشلة باستخدام نهج منهجي.
التمرين 1: انتهاء المهلة
كود المشكلة
# buggy_timeout.py
import time
import json
def lambda_handler(event, context):
"""
هذه الوظيفة لديها مشكلة انتهاء المهلة
"""
print("Starting processing...")
# محاكاة معالجة طويلة
data = event.get('data', [])
for item in data:
# معالجة بطيئة جدًا
time.sleep(2) # 2 ثانية لكل عنصر!
print(f"Processed: {item}")
return {
'statusCode': 200,
'body': json.dumps({'processed': len(data)})
}
التكوين
- انتهاء المهلة: 3 ثواني
- الحمولة:
{"data": ["a", "b", "c", "d", "e"]}
الأسئلة
- لماذا تفشل هذه الوظيفة؟
- احسب الوقت الإجمالي اللازم
- اقترح حلين مختلفين
💡 الحل
1. لماذا:
- 5 عناصر × 2 ثانية = 10 ثواني كحد أدنى
- انتهاء المهلة = 3 ثواني
- يتم إيقاف الوظيفة قبل الانتهاء
2. الوقت اللازم:
- المعالجة: 5 × 2s = 10s
- الحمل الزائد لـ Lambda: ~100ms
- الإجمالي: ~10.1 ثانية
3. الحلول:
الحل أ: زيادة انتهاء المهلة
aws lambda update-function-configuration \
--function-name buggy-timeout \
--timeout 30
الحل ب: تحسين الكود
import json
from concurrent.futures import ThreadPoolExecutor
def process_item(item):
# معالجة (محاكاة مع تقليل sleep)
return f"Processed: {item}"
def lambda_handler(event, context):
data = event.get('data', [])
# معالجة متوازية
with ThreadPoolExecutor(max_workers=5) as executor:
results = list(executor.map(process_item, data))
return {
'statusCode': 200,
'body': json.dumps({'results': results})
}
التمرين 2: خطأ في الأذونات
الكود
# buggy_permissions.py
import json
import boto3
def lambda_handler(event, context):
"""
هذه الوظيفة تحاول القراءة من S3
"""
s3 = boto3.client('s3')
bucket = event['bucket']
key = event['key']
try:
response = s3.get_object(Bucket=bucket, Key=key)
content = response['Body'].read().decode('utf-8')
return {
'statusCode': 200,
'body': json.dumps({'content': content[:100]})
}
except Exception as e:
return {
'statusCode': 500,
'body': json.dumps({'error': str(e)})
}
الخطأ المستلم
{
"statusCode": 500,
"body": "{\"error\": \"An error occurred (AccessDenied) when calling the GetObject operation: Access Denied\"}"
}
الأسئلة
- ما هو سبب الخطأ؟
- ما هي سياسة IAM التي يجب إضافتها؟
- اكتب أمر AWS CLI للتصحيح
💡 الحل
1. السبب:
دور تنفيذ Lambda ليس لديه إذن s3:GetObject
2. سياسة IAM لإضافتها:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
3. أوامر CLI:
# إنشاء السياسة
cat > s3-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::my-bucket/*"
}]
}
EOF
# إرفاق بالدور
aws iam put-role-policy \
--role-name lambda-role \
--policy-name S3ReadAccess \
--policy-document file://s3-policy.json
التمرين 3: نفاد الذاكرة
كود المشكلة
# buggy_memory.py
import json
def lambda_handler(event, context):
"""
هذه الوظيفة لديها مشكلة في الذاكرة
"""
size = event.get('size', 1000000)
# إنشاء قائمة ضخمة في الذاكرة
data = []
for i in range(size):
data.append({
'id': i,
'name': f'Item {i}',
'description': 'A' * 1000 # 1KB لكل عنصر
})
return {
'statusCode': 200,
'body': json.dumps({'count': len(data)})
}
التكوين
- الذاكرة: 128 MB
- الحمولة:
{"size": 100000}(100K عناصر × ~1KB = ~100MB)
الأسئلة
- لماذا تفشل الوظيفة؟
- ما هي الذاكرة التي توصي بها؟
- كيف يمكن التحسين دون زيادة الذاكرة؟
💡 الحل
1. لماذا:
- 100,000 عنصر × ~1KB = ~100MB من البيانات
- الحمل الزائد لـ Python/Lambda: ~30-50MB
- الإجمالي: ~130-150MB > 128MB المكونة
2. الذاكرة الموصى بها:
- الحد الأدنى: 256 MB (مع هامش)
- الموصى به: 512 MB (للأمان)
aws lambda update-function-configuration \
--function-name buggy-memory \
--memory-size 512
3. التحسين دون زيادة الذاكرة:
import json
def lambda_handler(event, context):
size = event.get('size', 1000000)
# معالجة بالدفعات باستخدام مولد
def process_batch(start, end):
for i in range(start, end):
yield {'id': i, 'processed': True}
# معالجة بالقطع من 10000
batch_size = 10000
total_processed = 0
for batch_start in range(0, size, batch_size):
batch_end = min(batch_start + batch_size, size)
# معالجة الدفعة (لا يحتفظ بكل شيء في الذاكرة)
for item in process_batch(batch_start, batch_end):
total_processed += 1
# تحرير الذاكرة بين الدفعات
return {
'statusCode': 200,
'body': json.dumps({'processed': total_processed})
}
التمرين 4: لم يتم العثور على المعالج
التكوين
- الملف:
my_function.py - المعالج المكون:
lambda_function.handler
الخطأ
{
"errorMessage": "Unable to import module 'lambda_function': No module named 'lambda_function'",
"errorType": "Runtime.ImportModuleError"
}
الأسئلة
- ما هو خطأ التكوين؟
- ما هي قيمة المعالج الصحيحة؟
- اذكر 3 أخطاء شائعة للمعالج
💡 الحل
1. الخطأ:
المعالج مكون لـ lambda_function.handler لكن الملف يسمى my_function.py
2. المعالج الصحيح:
my_function.handler
الصيغة: <nom_fichier_sans_extension>.<nom_fonction>
3. الأخطاء الشائعة:
- اسم الملف غير صحيح (
lambda_functionمقابلmy_function) - اسم الوظيفة غير صحيح (
handlerمقابلlambda_handler) - الملف في مجلد فرعي (
src/handler.mainبدلاً منhandler.main) - تم تضمين الامتداد عن طريق الخطأ (
handler.py.main) - حالة الأحرف غير صحيحة (
Handlerمقابلhandler)
التمرين 5: التشخيص الكامل
السيناريو
وظيفة Lambda تعيد بشكل متقطع أخطاء. فيما يلي المعلومات المتاحة:
سجلات CloudWatch:
START RequestId: abc-123
[INFO] Connecting to database...
END RequestId: abc-123
REPORT RequestId: abc-123 Duration: 29987.45 ms Billed Duration: 30000 ms Memory Size: 256 MB Max Memory Used: 89 MB Init Duration: 1234.56 ms
START RequestId: def-456
[INFO] Connecting to database...
[ERROR] Connection timed out
END RequestId: def-456
REPORT RequestId: def-456 Duration: 30000.00 ms Billed Duration: 30000 ms Memory Size: 256 MB Max Memory Used: 67 MB
التكوين:
- انتهاء المهلة: 30 ثانية
- الذاكرة: 256 MB
- VPC: نعم (شبكة فرعية خاصة)
الأسئلة
املأ جدول التشخيص:
| العنصر | الملاحظة | المشكلة المحتملة | الإجراء |
|---|---|---|---|
| Duration | ? | ? | ? |
| Memory | ? | ? | ? |
| Init Duration | ? | ? | ? |
| Error message | ? | ? | ? |
| VPC | ? | ? | ? |
💡 الحل
| العنصر | الملاحظة | المشكلة المحتملة | الإجراء |
|---|---|---|---|
| Duration | ~30s (انتهاء المهلة) | اتصال DB بطيء/محظور | انتهاء مهلة DB + إعادة المحاولة |
| Memory | 67-89 MB / 256 MB | حسنًا، لا توجد مشكلة في الذاكرة | - |
| Init Duration | 1234ms | بدء بارد مرتفع | تحسين أو Provisioned |
| Error message | Connection timed out | DB غير قابلة للوصول | تحقق من SG، NAT |
| VPC | شبكة فرعية خاصة | لا يوجد NAT للخروج إلى الإنترنت؟ | إضافة بوابة NAT |
التشخيص: الوظيفة في VPC خاص بدون بوابة NAT. لا يمكنها الوصول إلى قاعدة البيانات الخارجية.
الحلول:
- إضافة بوابة NAT إلى الشبكة الفرعية الخاصة
- أو وضع قاعدة البيانات في نفس VPC
- أو استخدام VPC Endpoints إذا كانت قاعدة البيانات خدمة AWS
- إضافة انتهاء مهلة الاتصال في الكود
التمرين 6: كتابة سجلات ذات جودة
الكود قبل (سجلات سيئة)
def lambda_handler(event, context):
print("Starting")
# ... code ...
print("Done")
return result
التمرين
أعد كتابة الكود مع سجلات ذات جودة تسهل استكشاف الأخطاء وإصلاحها:
💡 الحل
import json
import logging
# تكوين المسجل
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
# سجل منظم للإدخال
logger.info(json.dumps({
'action': 'start',
'request_id': context.aws_request_id,
'event_keys': list(event.keys()),
'remaining_time_ms': context.get_remaining_time_in_millis()
}))
try:
# منطقك
user_id = event.get('user_id')
logger.info(f"Processing user: {user_id}")
result = process_user(user_id)
# سجل النجاح
logger.info(json.dumps({
'action': 'complete',
'request_id': context.aws_request_id,
'user_id': user_id,
'status': 'success'
}))
return {'statusCode': 200, 'body': json.dumps(result)}
except Exception as e:
# سجل خطأ مفصل
logger.error(json.dumps({
'action': 'error',
'request_id': context.aws_request_id,
'error_type': type(e).__name__,
'error_message': str(e),
'user_id': event.get('user_id')
}), exc_info=True)
return {'statusCode': 500, 'body': json.dumps({'error': str(e)})}
التسليم
الوثيقة المطلوب إنتاجها
- حلول للتمارين الستة
- جدول التشخيص المكتمل
- الكود المصحح لكل خطأ
- توصيات لأفضل الممارسات
معايير التقييم
| المعيار | النقاط |
|---|---|
| التشخيص الصحيح | /25 |
| الحلول المناسبة | /25 |
| الكود المصحح الوظيفي | /25 |
| جودة السجلات | /15 |
| الوثائق | /10 |
| الإجمالي | /100 |
الأسبوع التالي: MODULE 13 - المراقبة