Serverless Architecture

Функции как сервис (FaaS)

Запускай код без управления серверами

Что такое Serverless?

Serverless — архитектурный подход, при котором приложение состоит из функций, которые запускаются по требованию, без управления серверами.

🔹 Традиционный подход

Приложение → Сервер → БД
    ↓
  Управление серверами
  Масштабирование
  Мониторинг
  Обновления

❌ Нужно управлять инфраструктурой

✅ Serverless подход

Функция → Cloud Provider → БД
    ↓
  Провайдер управляет всем
  Автоматическое масштабирование
  Платишь только за использование

✅ Не нужно управлять серверами

🔹 Характеристики Serverless

  • Нет серверов — провайдер управляет инфраструктурой
  • Автоматическое масштабирование — от 0 до миллионов запросов
  • Pay-per-use — платишь только за выполнение
  • Быстрое развертывание — загрузил код и работает
  • Высокая доступность — провайдер обеспечивает uptime

FaaS платформы

🔹 AWS Lambda

# 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

# 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}
# Автоматически масштабируется
# Платишь только за запросы

🔹 Azure Functions

# 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

🔹 Google Cloud Functions

# 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 Framework

Фреймворк для развертывания serverless функций

🔹 serverless.yml

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

# 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}

Паттерны Serverless

🔹 API Gateway Pattern

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

🔹 Event-Driven Pattern

# 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'])

🔹 Step Functions (Workflow)

{
  "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 функций

Преимущества Serverless

  • Нет управления серверами — провайдер делает всё
  • Автоматическое масштабирование — от 0 до миллионов
  • Cost-effective — платишь только за использование
  • Быстрое развертывание — загрузил код и работает
  • Высокая доступность — провайдер обеспечивает uptime
  • Фокус на коде — не нужно думать об инфраструктуре

Недостатки Serverless

  • Cold start — первое выполнение медленное
  • Таймауты — ограничение времени выполнения (15 минут)
  • Vendor lock-in — привязка к провайдеру
  • Отладка — сложнее отлаживать распределённые функции
  • Локальная разработка — сложнее тестировать локально
  • Стоимость — может быть дорого при высокой нагрузке

💡 Когда использовать Serverless?

Сценарий Рекомендация
API endpoints ✅ Отлично подходит
Обработка файлов ✅ Хорошо
События и триггеры ✅ Отлично
Долгие задачи (>15 мин) ❌ Не подходит
Высокая постоянная нагрузка ⚠️ Может быть дорого

Практический пример: Image Processing

🔹 Архитектура

User → API Gateway → Lambda: upload_image
              ↓
         S3 Bucket (raw images)
              ↓
         S3 Event → Lambda: process_image
              ↓
         S3 Bucket (processed images)
              ↓
         DynamoDB (metadata)
              ↓
         Lambda: send_notification

🔹 Lambda: upload_image

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'})
    }

🔹 Lambda: process_image

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

  1. Функции как единица развертывания — каждая функция независима
  2. Событийная архитектура — функции запускаются по событиям
  3. Stateless — функции не хранят состояние
  4. Автоматическое масштабирование — провайдер масштабирует автоматически
  5. Pay-per-use — платишь только за выполнение
"Serverless — это не про отсутствие серверов. Это про то, что ты не думаешь о серверах.
Провайдер управляет инфраструктурой, ты пишешь код."

📚 Платформы

  • AWS Lambda — самый популярный
  • Azure Functions — Microsoft
  • Google Cloud Functions — Google
  • Vercel — для фронтенда
  • Netlify Functions — для статических сайтов