إنشاء وظائف Lambda
طرق النشر
نظرة عامة
┌─────────────────────────────────────────────────────────────┐
│ MÉTHODES DE DÉPLOIEMENT │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. CONSOLE AWS │
│ ───────────── │
│ واجهة ويب، مثالية للاختبارات/التعلم │
│ ✅ بسيطة ❌ غير قابلة للأتمتة │
│ │
│ 2. AWS CLI │
│ ──────── │
│ سطر الأوامر، قابلة للبرمجة │
│ ✅ قابلة للأتمتة ⚠️ أكثر تعقيدًا │
│ │
│ 3. SAM (Serverless Application Model) │
│ ─────────────────────────────────── │
│ إطار عمل AWS للخدمات بدون خادم │
│ ✅ IaC ✅ اختبار محلي ✅ أفضل الممارسات │
│ │
│ 4. CloudFormation / Terraform │
│ ────────────────────────────── │
│ بنية تحتية ككود كاملة │
│ ✅ إنتاجية ✅ قابلة للتكرار │
│ │
└─────────────────────────────────────────────────────────────┘
الإنشاء عبر AWS CLI
الخطوة 1: إنشاء دور IAM
# 1. إنشاء ملف trust policy
cat > trust-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
# 2. إنشاء الدور
aws iam create-role \
--role-name lambda-basic-role \
--assume-role-policy-document file://trust-policy.json
# 3. إرفاق السياسة الأساسية (logs)
aws iam attach-role-policy \
--role-name lambda-basic-role \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
الخطوة 2: إنشاء الكود
# lambda_function.py
import json
def lambda_handler(event, context):
"""
وظيفة Hello World بسيطة
"""
# استرجاع الاسم من الحدث
name = event.get('name', 'World')
# إنشاء الرسالة
message = f"Hello, {name}!"
# تسجيل
print(f"Processing request for: {name}")
# إرجاع الاستجابة
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json'
},
'body': json.dumps({
'message': message,
'input': event
})
}
الخطوة 3: حزم ونشر
# 1. ضغط الكود
zip function.zip lambda_function.py
# 2. إنشاء الوظيفة
aws lambda create-function \
--function-name hello-world \
--runtime python3.11 \
--role arn:aws:iam::123456789012:role/lambda-basic-role \
--handler lambda_function.lambda_handler \
--zip-file fileb://function.zip \
--timeout 30 \
--memory-size 256
# 3. اختبار الوظيفة
aws lambda invoke \
--function-name hello-world \
--payload '{"name": "AWS"}' \
--cli-binary-format raw-in-base64-out \
response.json
# 4. عرض الاستجابة
cat response.json
متغيرات البيئة
التكوين
# إضافة متغيرات البيئة
aws lambda update-function-configuration \
--function-name hello-world \
--environment 'Variables={
DB_HOST=mydb.example.com,
DB_NAME=production,
LOG_LEVEL=INFO
}'
الاستخدام في الكود
import os
import json
def lambda_handler(event, context):
# قراءة متغيرات البيئة
db_host = os.environ.get('DB_HOST', 'localhost')
db_name = os.environ.get('DB_NAME', 'default')
log_level = os.environ.get('LOG_LEVEL', 'DEBUG')
print(f"[{log_level}] Connecting to {db_host}/{db_name}")
return {
'statusCode': 200,
'body': json.dumps({
'db_host': db_host,
'db_name': db_name
})
}
تفعيل API Gateway
الهندسة المعمارية
┌─────────────────────────────────────────────────────────────┐
│ API GATEWAY + LAMBDA │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ عميل │ │
│ │ │ │ │
│ │ │ GET /hello?name=AWS │ │
│ │ ▼ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ API Gateway │ │ │
│ │ │ │ │ │
│ │ │ • المصادقة │ │
│ │ │ • تحديد المعدل │ │
│ │ │ • CORS │ │
│ │ └────────┬────────┘ │ │
│ │ │ │ │
│ │ │ Invoke │ │
│ │ ▼ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ Lambda │ │ │
│ │ │ hello-world │ │ │
│ │ └────────┬────────┘ │ │
│ │ │ │ │
│ │ │ Response │ │
│ │ ▼ │ │
│ │ {"message": "Hello, AWS!"} │ │
│ │ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
إنشاء API
# 1. إنشاء API HTTP (v2، أبسط)
aws apigatewayv2 create-api \
--name hello-api \
--protocol-type HTTP \
--target arn:aws:lambda:us-east-1:123456789012:function:hello-world
# 2. إضافة الإذن لـ API Gateway
aws lambda add-permission \
--function-name hello-world \
--statement-id apigateway-invoke \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com
كود لـ API Gateway
import json
def lambda_handler(event, context):
"""
معالج لـ API Gateway HTTP API
"""
# استخراج المعلمات
query_params = event.get('queryStringParameters', {}) or {}
name = query_params.get('name', 'World')
# استخراج المسار
path = event.get('rawPath', '/')
method = event.get('requestContext', {}).get('http', {}).get('method', 'GET')
print(f"{method} {path} - name={name}")
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*' # CORS
},
'body': json.dumps({
'message': f'Hello, {name}!',
'path': path,
'method': method
})
}
تفعيل S3
التكوين
# إضافة الإذن لـ S3
aws lambda add-permission \
--function-name process-upload \
--statement-id s3-trigger \
--action lambda:InvokeFunction \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::my-bucket \
--source-account 123456789012
# تكوين التفعيل على الدلو
aws s3api put-bucket-notification-configuration \
--bucket my-bucket \
--notification-configuration '{
"LambdaFunctionConfigurations": [
{
"LambdaFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:process-upload",
"Events": ["s3:ObjectCreated:*"],
"Filter": {
"Key": {
"FilterRules": [
{"Name": "suffix", "Value": ".jpg"}
]
}
}
}
]
}'
كود لـ S3
import json
import boto3
s3 = boto3.client('s3')
def lambda_handler(event, context):
"""
معالجة الملفات المرفوعة في S3
"""
for record in event['Records']:
# استخراج معلومات الملف
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
size = record['s3']['object']['size']
print(f"Nouveau fichier: s3://{bucket}/{key} ({size} bytes)")
# تنزيل الملف
response = s3.get_object(Bucket=bucket, Key=key)
content = response['Body'].read()
# معالجة الملف (مثال: تغيير حجم الصورة)
# processed = process_image(content)
# حفظ النتيجة
# s3.put_object(Bucket=bucket, Key=f"processed/{key}", Body=processed)
print(f"Traitement terminé pour {key}")
return {
'statusCode': 200,
'body': json.dumps('Traitement terminé')
}
التبعيات (Layers)
المفهوم
┌─────────────────────────────────────────────────────────────┐
│ LAMBDA LAYERS │
├─────────────────────────────────────────────────────────────┤
│ │
│ Layers تسمح بمشاركة الكود/التبعيات بين عدة وظائف │
│ │
│ بدون Layers : │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Function A │ │ Function B │ │ Function C │ │
│ │ + numpy │ │ + numpy │ │ + numpy │ │
│ │ + pandas │ │ + pandas │ │ + requests │ │
│ │ (50 MB) │ │ (50 MB) │ │ (30 MB) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ مع Layers : │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Function A │ │ Function B │ │ Function C │ │
│ │ (code only) │ │ (code only) │ │ (code only) │ │
│ │ (1 KB) │ │ (1 KB) │ │ (1 KB) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └─────────────────┼─────────────────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ Layer: libs │ │
│ │ numpy, pandas │ │
│ │ (50 MB) │ │
│ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
إنشاء Layer
# 1. إنشاء الهيكل
mkdir -p python/lib/python3.11/site-packages
# 2. تثبيت التبعيات
pip install requests -t python/lib/python3.11/site-packages/
# 3. ضغط
zip -r layer.zip python/
# 4. نشر layer
aws lambda publish-layer-version \
--layer-name my-dependencies \
--zip-file fileb://layer.zip \
--compatible-runtimes python3.11
# 5. إرفاق إلى وظيفة
aws lambda update-function-configuration \
--function-name hello-world \
--layers arn:aws:lambda:us-east-1:123456789012:layer:my-dependencies:1
أفضل الممارسات
┌─────────────────────────────────────────────────────────────┐
│ BONNES PRATIQUES LAMBDA │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ FAIRE │
│ ──────── │
│ • الحفاظ على الوظائف صغيرة ومركزة │
│ • استخدام متغيرات البيئة │
│ • إعادة استخدام الاتصالات (خارج المعالج) │
│ • تسجيل باستخدام print() أو logging │
│ • التعامل مع الأخطاء بشكل صحيح │
│ • تحديد مهلة مناسبة │
│ │
│ ❌ ÉVITER │
│ ───────── │
│ • الوظائف الأحادية │
│ • ترميز التكوينات بشكل ثابت │
│ • إنشاء اتصالات في المعالج │
│ • تجاهل الأخطاء │
│ • مهلة طويلة جدًا (إهدار في حالة الخطأ) │
│ │
│ كود محسن: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ import boto3 │ │
│ │ import os │ │
│ │ │ │
│ │ # اتصالات خارج المعالج (معاد استخدامها) │ │
│ │ dynamodb = boto3.resource('dynamodb') │ │
│ │ table = dynamodb.Table(os.environ['TABLE_NAME']) │ │
│ │ │ │
│ │ def lambda_handler(event, context): │ │
│ │ # معالج خفيف، اتصال معاد استخدامه │ │
│ │ return table.get_item(Key={'id': event['id']})│ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
ملخص
| الخطوة | الأمر |
|---|---|
| إنشاء دور | aws iam create-role |
| إنشاء وظيفة | aws lambda create-function |
| اختبار | aws lambda invoke |
| تحديث | aws lambda update-function-code |
| إضافة تفعيل | aws lambda add-permission |
القسم التالي: مختبر Lambda