Функции как сервис (FaaS)
Запускай код без управления серверами
Serverless — архитектурный подход, при котором приложение состоит из функций, которые запускаются по требованию, без управления серверами.
Приложение → Сервер → БД
↓
Управление серверами
Масштабирование
Мониторинг
Обновления
❌ Нужно управлять инфраструктурой
Функция → Cloud Provider → БД
↓
Провайдер управляет всем
Автоматическое масштабирование
Платишь только за использование
✅ Не нужно управлять серверами
# lambda_function.py
import json
def lambda_handler(event, context):
# Обработка события
name = event.get('name', 'World')
return {
'statusCode': 200,
'body': json.dumps({
'message': f'Hello, {name}!'
})
}
# Триггеры:
# - API Gateway (HTTP)
# - S3 (файлы)
# - DynamoDB (изменения)
# - SQS (очереди)
# - EventBridge (события)
# API Gateway → Lambda
import json
def lambda_handler(event, context):
# Получаем данные из запроса
body = json.loads(event['body'])
user_id = body.get('user_id')
# Обработка
user = get_user(user_id)
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json'
},
'body': json.dumps(user.to_dict())
}
# Endpoint: GET /users/{user_id}
# Автоматически масштабируется
# Платишь только за запросы
# function_app.py
import azure.functions as func
def main(req: func.HttpRequest) -> func.HttpResponse:
name = req.params.get('name')
return func.HttpResponse(
f"Hello, {name}!",
status_code=200
)
# Триггеры:
# - HTTP
# - Timer (cron)
# - Queue
# - Blob Storage
# - Cosmos DB
# main.py
def hello_world(request):
name = request.args.get('name', 'World')
return f'Hello, {name}!'
# Триггеры:
# - HTTP
# - Cloud Storage
# - Pub/Sub
# - Firestore
# - Cloud Scheduler
Фреймворк для развертывания serverless функций
service: my-service
provider:
name: aws
runtime: python3.11
region: us-east-1
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
- s3:
bucket: my-bucket
event: s3:ObjectCreated:*
process:
handler: handler.process
events:
- sqs:
arn: arn:aws:sqs:us-east-1:123456789:my-queue
timeout: 30
memorySize: 512
resources:
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: my-bucket
# handler.py
def hello(event, context):
return {
'statusCode': 200,
'body': 'Hello, World!'
}
def process(event, context):
# Обработка события из SQS
for record in event['Records']:
data = json.loads(record['body'])
process_data(data)
return {'statusCode': 200}
Client → API Gateway → Lambda Functions
↓
Routing
Authentication
Rate Limiting
Caching
# API Gateway маршрутизирует запросы
# GET /users → Lambda: get_users
# POST /users → Lambda: create_user
# GET /users/{id} → Lambda: get_user
# S3 → Lambda (обработка файлов)
def process_file(event, context):
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
# Обработка файла
process_s3_file(bucket, key)
# DynamoDB → Lambda (обработка изменений)
def handle_dynamodb_change(event, context):
for record in event['Records']:
if record['eventName'] == 'INSERT':
handle_insert(record['dynamodb'])
elif record['eventName'] == 'MODIFY':
handle_update(record['dynamodb'])
{
"StartAt": "ProcessOrder",
"States": {
"ProcessOrder": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:process_order",
"Next": "ProcessPayment"
},
"ProcessPayment": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:process_payment",
"Next": "SendNotification"
},
"SendNotification": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:send_notification",
"End": true
}
}
}
💡 Step Functions координируют выполнение нескольких Lambda функций
| Сценарий | Рекомендация |
|---|---|
| API endpoints | ✅ Отлично подходит |
| Обработка файлов | ✅ Хорошо |
| События и триггеры | ✅ Отлично |
| Долгие задачи (>15 мин) | ❌ Не подходит |
| Высокая постоянная нагрузка | ⚠️ Может быть дорого |
User → API Gateway → Lambda: upload_image
↓
S3 Bucket (raw images)
↓
S3 Event → Lambda: process_image
↓
S3 Bucket (processed images)
↓
DynamoDB (metadata)
↓
Lambda: send_notification
import boto3
import json
s3 = boto3.client('s3')
def lambda_handler(event, context):
# Получаем изображение из запроса
image_data = event['body']
# Сохраняем в S3
s3.put_object(
Bucket='raw-images',
Key=f"image_{context.request_id}.jpg",
Body=image_data
)
return {
'statusCode': 200,
'body': json.dumps({'message': 'Image uploaded'})
}
import boto3
from PIL import Image
s3 = boto3.client('s3')
dynamodb = boto3.client('dynamodb')
def lambda_handler(event, context):
# Получаем информацию о загруженном файле
bucket = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
# Загружаем изображение
response = s3.get_object(Bucket=bucket, Key=key)
image = Image.open(response['Body'])
# Обрабатываем (resize, compress)
processed_image = image.resize((800, 600))
# Сохраняем обработанное изображение
processed_key = f"processed/{key}"
s3.put_object(
Bucket='processed-images',
Key=processed_key,
Body=processed_image.tobytes()
)
# Сохраняем метаданные в DynamoDB
dynamodb.put_item(
TableName='images',
Item={
'key': {'S': key},
'processed_key': {'S': processed_key},
'status': {'S': 'processed'}
}
)
return {'statusCode': 200}
"Serverless — это не про отсутствие серверов. Это про то, что ты не думаешь о серверах.
Провайдер управляет инфраструктурой, ты пишешь код."