Serverless-обработка файлов: Lambda + S3 trigger под ключ
При загрузке изображений в S3 нужно автоматически генерировать thumbnails, но Lambda не справляется с большими файлами. Нужна отказоустойчивая архитектура с очередями и мониторингом. Мы — команда с опытом serverless-разработки — построили десятки таких систем. В этой статье разберём типовую архитектуру, обработку ошибок и подводные камни.
Lambda + S3 trigger — классический serverless паттерн для обработки файлов. Файл загружается в S3, событие автоматически запускает Lambda, которая обрабатывает файл и сохраняет результат. Не нужен постоянно работающий сервер, масштабирование автоматическое. Однако без правильной схемы с очередями вы рискуете потерять события. Экономия на инфраструктуре может достигать 70% по сравнению с выделенным сервером, а стоимость обработки одного файла снижается в 3-5 раз. Рассмотрим, как построить production-grade обработку с очередями, DLQ и мониторингом.
Какие задачи решает Lambda + S3 и базовая архитектура
Типовые задачи: генерация thumbnail при загрузке изображения, конвертация видео в разные форматы и разрешения, обработка CSV/Excel файлов с импортом данных в БД, PDF-генерация из шаблонов, антивирусное сканирование загружаемых файлов, OCR и извлечение текста из документов, трансформация данных (XML → JSON, нормализация).
| Тип файла | Примеры | Рекомендуемый подход |
|---|---|---|
| Изображения | JPG, PNG, WebP | Lambda + Pillow |
| Документы | PDF, DOCX | Lambda + pdfminer, python-docx |
| Видео | MP4, AVI | AWS MediaConvert |
| Таблицы | CSV, XLSX | Lambda + pandas (стриминг) |
| Архивы | ZIP, RAR | Lambda + zipfile (стриминг) |
Базовая архитектура:
[Пользователь] → S3 upload → [S3 Event Notification]
↓
[Lambda Function]
↓
[Обработанный файл → S3 Output]
[Метаданные → DynamoDB]
[Нотификация → SQS/SNS]
# S3 bucket для входящих файлов
resource "aws_s3_bucket" "uploads" {
bucket = "myapp-uploads"
}
# S3 bucket для обработанных файлов
resource "aws_s3_bucket" "processed" {
bucket = "myapp-processed"
}
# Объединённая конфигурация: S3 → SNS → SQS
resource "aws_s3_bucket_notification" "upload_trigger" {
bucket = aws_s3_bucket.uploads.id
topic {
topic_arn = aws_sns_topic.file_events.arn
events = ["s3:ObjectCreated:*"]
}
}
resource "aws_sns_topic_subscription" "to_sqs" {
topic_arn = aws_sns_topic.file_events.arn
protocol = "sqs"
endpoint = aws_sqs_queue.file_processing.arn
}
Как масштабировать обработку при пиковых нагрузках?
Lambda масштабируется автоматически, но при резком всплеске загрузок может возникнуть троттлинг. Мы используем SQS-очередь для буферизации: S3 → SNS → SQS → Lambda. Это гарантирует, что ни одно событие не потеряется. При превышении лимита concurrent executions очередь накапливает сообщения, и Lambda обрабатывает их по мере освобождения. Для критичных задач настраиваем Reserved Concurrency.
Обработчик Lambda и большие файлы
import boto3
import json
import os
from urllib.parse import unquote_plus
from PIL import Image
import io
s3 = boto3.client('s3')
def handler(event, context):
results = []
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = unquote_plus(record['s3']['object']['key'])
try:
result = process_image(bucket, key)
results.append({'key': key, 'status': 'success', **result})
except Exception as e:
print(f"Error processing {key}: {e}")
results.append({'key': key, 'status': 'error', 'error': str(e)})
return results
def process_image(bucket: str, key: str) -> dict:
# Скачать оригинал
obj = s3.get_object(Bucket=bucket, Key=key)
image_data = obj['Body'].read()
image = Image.open(io.BytesIO(image_data))
thumbnails = {}
for size_name, (width, height) in [('sm', (150, 150)), ('md', (400, 400)), ('lg', (800, 800))]:
thumb = image.copy()
thumb.thumbnail((width, height), Image.LANCZOS)
buffer = io.BytesIO()
thumb.save(buffer, format=image.format or 'JPEG', quality=85)
buffer.seek(0)
output_key = key.replace('images/', f'thumbnails/{size_name}/')
s3.put_object(
Bucket=os.environ['OUTPUT_BUCKET'],
Key=output_key,
Body=buffer,
ContentType=f'image/{(image.format or "JPEG").lower()}'
)
thumbnails[size_name] = output_key
return {'thumbnails': thumbnails, 'original_size': image.size}
Lambda имеет ограничения: /tmp до 10 ГБ, timeout до 15 минут, память до 10 ГБ. Для файлов >100 МБ применяем стриминг, обрабатывая данные по частям без загрузки в память целиком.
Почему SNS+SQS надёжнее прямого вызова Lambda?
S3 event notifications не поддерживают DLQ напрямую. Если Lambda завершится ошибкой, событие теряется. Схема с SNS и SQS гарантирует доставку: неудачные вызовы после N попыток попадают в DLQ. Вы сможете проанализировать и перезапустить обработку. Это соответствует best practices AWS для продакшена.
Подробнее о конфигурации DLQ
Для SQS-очереди настраивается redrive policy: после, например, 5 неудачных попыток сообщение перемещается в DLQ. Это позволяет не терять события и анализировать ошибки.
Lambda vs ECS: что выбрать?
| Критерий | Lambda | ECS Fargate |
|---|---|---|
| Макс. время выполнения | 15 мин | Не ограничено |
| Макс. память | 10 ГБ | 30 ГБ |
| Стоимость | За миллисекунды | За vCPU/час |
| Масштабирование | Мгновенное | 30–60 сек |
| Оптимально для | Краткие задачи (<15 мин) | Долгие задачи, high memory |
Для обработки изображений и документов Lambda проще и дешевле. Для видео-транскодинга используем MediaConvert.
Конфигурация Lambda для обработки файлов
resource "aws_lambda_function" "processor" {
filename = "processor.zip"
function_name = "file-processor"
role = aws_iam_role.processor.arn
handler = "handler.handler"
runtime = "python3.12"
timeout = 300
memory_size = 1024
ephemeral_storage {
size = 2048
}
environment {
variables = {
OUTPUT_BUCKET = aws_s3_bucket.processed.bucket
}
}
}
Мониторинг и метрики
- Число обработанных файлов в час
- Среднее время обработки по типу файла
- Error rate + содержимое DLQ
- Lambda duration distribution
CloudWatch Dashboard с этими метриками + алерт при росте DLQ.
Что входит в работу и ориентировочные сроки
- Разработка Lambda-функции на Python (или Node.js/Go) под ваш тип файлов
- Инфраструктура Terraform / Pulumi с S3, SNS, SQS, DLQ
- Настройка мониторинга CloudWatch + алерты
- Код-ревью и тестирование на нагрузку до 1000 файлов/мин
- Документация архитектуры и инструкция по деплою
- Обучение команды заказчика (1-2 часа)
- Поддержка 2 недели после сдачи
Ориентировочные сроки:
- Анализ требований и прототип — 2-3 дня
- Полный pipeline с DLQ, мониторингом — 4-6 дней
- Интеграция с вашим приложением (API Gateway, Cognito — опционально) — 2-5 дней
Реальные сроки зависят от сложности обработки. Свяжитесь с нами — оценим ваш проект за 1 день. Закажите консультацию и получите предварительную оценку без обязательств.







