Загрузка и хранилище фотографий

Итоговая задача, собирающая весь курс: загрузка, хранение, обработка и быстрая раздача фото.

Фотосервис — система загрузки, хранения и раздачи изображений, где главный вызов — тяжёлый бинарный трафик и асинхронная обработка превью.

Требования и масштаб

Функционально: загрузить фото, получить разные размеры (превью/полноразмер), посмотреть свои/чужие фото. Нефункционально: быстрая раздача по миру, надёжное хранение, обработка не должна блокировать пользователя. Из оценки трафика (раздел про пропускную способность) сразу следует: статика тяжёлая -> нужен CDN.

Загрузка: прямо в хранилище

Гнать гигабайты через приложение — расточительно. Клиент получает presigned URL и заливает оригинал прямо в объектное хранилище. Приложение лишь регистрирует метаданные.

1) Клиент -> App: "хочу загрузить" -> presigned URL
2) Клиент -> S3: PUT оригинал (минуя App)
3) App записывает Photo(id, owner, s3_key, status=processing)

Асинхронная обработка

После загрузки нужно сделать превью разных размеров, проверить контент. Это тяжело и не должно блокировать ответ. Кладём задачу в очередь, worker'ы генерируют варианты и обновляют статус.

S3 (оригинал) -> [Очередь] -> Worker: ресайз -> S3 (превью) -> status=ready

Раздача через CDN

КомпонентРоль
Объектное хранилищеОригиналы и превью (источник истины)
CDNКэш у границы, быстрая раздача по миру
БДМетаданные: владелец, ключи, статус, дата
Очередь + worker'ыАсинхронные превью и модерация

Как работает под капотом

Эта задача — сборка всего курса. Прямая загрузка снимает трафик с приложения (как presigned URL из урока про CDN). Очередь развязывает обработку (урок про асинхронность). CDN решает тяжёлый трафик раздачи (урок про пропускную способность и CDN). БД хранит только лёгкие метаданные, файлы — в хранилище. Лента фотографий пользователя строится теми же приёмами, что и новостная лента.

Частые ошибки

  • Принимать загрузку через приложение и упираться в его трафик.
  • Генерировать превью синхронно и заставлять пользователя ждать.
  • Раздавать оригиналы напрямую из одного региона без CDN.

Итог

  • Загрузка — напрямую в хранилище через presigned URL.
  • Обработка превью — асинхронно через очередь и worker'ы.
  • Раздача — через CDN; БД хранит только метаданные.
Проверьте себя
1. Как правильно организовать загрузку больших фото?
AГнать файл через приложение в БД
BКлиент заливает оригинал прямо в объектное хранилище по presigned URL
CХранить фото в кэше Redis
DОтправлять фото по WebSocket на балансировщик
2. Почему генерацию превью делают асинхронно?
AЧтобы превью были красивее
BЧтобы не блокировать пользователя тяжёлой обработкой в момент загрузки
CЧтобы не использовать очередь
DЭто требование объектного хранилища
3. Что хранится в реляционной БД фотосервиса?
AСами файлы изображений
BМетаданные: владелец, ключи объектов, статус, дата
CКэш CDN
DWebSocket-соединения