Как работает загрузка файлов в масштабе?
Задумывались ли вы, что на самом деле происходит после нажатия кнопки «Загрузить»?
Вы выбираете файл, и через несколько секунд он появляется в Google Drive или Amazon S3. Но за этой простой кнопкой стоит высокооптимизированная распределенная система, предназначенная для обработки миллионов загрузок каждый день.
Проектирование системы загрузок Google Drive и Amazon S3

Наивный подход ❌
Новичок может подумать, что процесс выглядит так:
Клиент
|
|
Загрузить файл
|
v
Сервер
|
|
Сохранить файл
|
v
Хранилище
Кажется простым...
Но представьте:
- Видео размером 1 ГБ
- 10 миллионов пользователей
- Медленный интернет
- Сбои сети
- Падения сервера
Такая архитектура быстро выйдет из строя.
Проблемы:
- Пропускная способность сервера становится узким местом
- Высокая загрузка ЦП
- Загрузка начинается заново при обрыве соединения
- Сложно масштабировать
Поэтому компании используют гораздо более умную архитектуру.
Шаг 1: Пользователь выбирает файл
Когда вы выбираете файл, клиент немедленно собирает метаданные:
{
filename: "отпуск.mp4",
size: 2.1 ГБ,
type: "video/mp4"
}
Обратите внимание:
Фактический файл еще не загружается.
Подготавливаются только метаданные.
Шаг 2: Клиент отправляет метаданные в API
Клиент
|
| filename
| size
| contentType
|
v
API-шлюз
API проверяет:
- Аутентификацию пользователя
- Квоту хранилища
- Тип файла
- Разрешения
Если все валидно, процесс продолжается.
Шаг 3: Сервер генерирует предварительно подписанный URL
Вместо отправки файла через сервер приложений, сервер запрашивает безопасный URL для загрузки.
Сервер
|
|
Сгенерировать URL загрузки
|
|
v
Amazon S3
Пример:
https://bucket.s3.amazonaws.com/file123
?signature=abcxyz
&expires=600
Это называется предварительно подписанный URL.
Он:
- Временный
- Безопасный
- С ограниченными правами
- Автоматически истекает
Зачем использовать предварительно подписанные URL?
Без них:
Клиент
|
|
Сервер приложений
|
|
Хранилище
Каждый байт проходит через ваш сервер.
Плохая идея.
С предварительно подписанными URL:
Клиент
|---------------------->
Хранилище
Сервер приложений обрабатывает только авторизацию.
Тяжелая загрузка файла идет напрямую в облачное хранилище.
Преимущества:
- Меньшая нагрузка на сервер
- Снижение стоимости
- Лучшая масштабируемость
- Более быстрая загрузка
Шаг 4: Клиент загружает напрямую в S3
Теперь клиент загружает напрямую:
Клиент
|
|
| Файл 2 ГБ
|
|
v
Amazon S3
Сервер больше не участвует в передаче данных.
Именно поэтому системы могут поддерживать миллионы пользователей одновременно.
Шаг 5: Хранилище возвращает успех
После загрузки:
S3
|
|
200 OK
|
|
Клиент
Теперь клиент знает, что загрузка прошла успешно.
Шаг 6: Сохранение метаданных
Сервер приложений сохраняет информацию, например:
Таблица файлов
-----------------------------------
id
userId
filename
storageKey
size
mimeType
createdAt
updatedAt
-----------------------------------
Обратите внимание:
База данных хранит метаданные, а не сам файл.
Фактический файл остается в объектном хранилище.
Итоговая архитектура
Метаданные
Клиент -------------------->
API
|
|
Сгенерировать предварительно подписанный URL
|
|
v
S3
^
|
|
Клиент -----------------------> Загрузить файл
|
|
Сохранить метаданные
|
v
База данных
Что произойдет, если интернет отключится?
Предположим:
Загрузка...
███████████░░░░░░░░
60%
Интернет отключается.
Без специальной обработки:
Начать заново ❌
Загружать файл 5 ГБ снова неприятно.
Современные системы избегают этого с помощью возобновляемых загрузок.
Возобновляемая загрузка
Вместо одного огромного файла клиент делит его на части.
Пример:
Файл
|
|
-----------------------------
Часть 1
Часть 2
Часть 3
Часть 4
Часть 5
-----------------------------
Возможно:
20 МБ каждая
Процесс загрузки:
Часть 1 ✅
Часть 2 ✅
Часть 3 ✅
Часть 4 ❌
Часть 5 ❌
Соединение потеряно.
Позже:
Переподключение
|
|
Возобновить
|
|
Часть 4 ✅
Часть 5 ✅
Загружаются только недостающие части.
Огромная экономия пропускной способности.
Многокомпонентная загрузка в Amazon S3
Amazon S3 поддерживает многокомпонентную загрузку:
Инициализировать загрузку
|
|
Загрузить часть 1
Загрузить часть 2
Загрузить часть 3
Загрузить часть 4
|
|
Завершить загрузку
Внутренне S3 собирает все части в один объект.
Преимущества:
- Повторная отправка отдельных частей
- Параллельная загрузка
- Лучшая надежность
- Более высокая производительность
Параллельная загрузка
Вместо:
Часть1
↓
Часть2
↓
Часть3
↓
Часть4
Системы делают:
Часть1 ----->
Часть2 ----->
Часть3 ----->
Часть4 ----->
Все сразу.
Это значительно сокращает время загрузки.
_Что насчет очень больших файлов?_
Для таких файлов как :
- 10 ГБ
- 20 ГБ
- 100 ГБ
Системы используют :
Разбиение на части
Многокомпонентная загрузка
Логика повторных попыток
Проверка контрольной суммы
Фоновая обработка
Это обеспечивает надежность даже в нестабильных сетях.
Как работает синхронизация между несколькими устройствами
Предположим, вы загружаете с ноутбука.
Ноутбук
|
|
Облачное хранилище
/ \
/ \
Телефон Планшет
После завершения загрузки:
- Метаданные обновляются
- Служба синхронизации обнаруживает изменения
- Другие устройства получают уведомления
- Загружаются только измененные файлы
Вот почему ваш телефон быстро показывает новый файл без ручного обновления.
_Почему компании не хранят файлы в базах данных?_
Представьте, что вы храните видео размером 2 ГБ прямо в MySQL или PostgreSQL.
Проблемы:
- Огромный рост базы данных
- Медленное резервное копирование
- Дорогая репликация
- Низкая производительность
Вместо этого:
База данных
↓
Хранит:
- имя файла
- владелец
- путь
- размер
- права доступа
Объектное хранилище
↓
Хранит:
Фактический бинарный файл
Такое разделение делает системы масштабируемыми и более простыми в обслуживании.
Реальный производственный поток
Пользователь
|
|
Выбрать файл
|
|
Отправить метаданные
|
v
API-шлюз
|
Аутентификация
|
Сгенерировать предварительно подписанный URL
|
v
Объектное хранилище
<--------------------
Прямая загрузка
|
|
Успех загрузки
|
|
Сохранить метаданные
|
v
База данных
|
|
Уведомить службу синхронизации
|
-----------------------
| |
Ноутбук Мобильный
| |
Синхронизировано ✅ Синхронизировано ✅
Вопросы для собеседования
Q1. Почему файлы не должны проходить через сервер приложений?
Потому что это создает узкое место по пропускной способности, увеличивает стоимость сервера и ограничивает масштабируемость. Прямая загрузка в объектное хранилище более эффективна.
Q2. Что такое предварительно подписанный URL?
Временный, безопасный URL, сгенерированный сервером, который позволяет клиенту загружать напрямую в объектное хранилище без раскрытия постоянных учетных данных.
Q3. Зачем хранить метаданные в базе данных, а не сам файл?
Базы данных оптимизированы для структурированных данных и запросов, тогда как объектное хранилище оптимизировано для надежного и экономичного хранения больших бинарных файлов.
Q4. Что такое многокомпонентная загрузка?
Она разбивает большой файл на несколько частей, которые могут быть загружены независимо, а затем объединены службой хранения в один объект.
Q5. Что такое возобновляемая загрузка?
Механизм, при котором прерванные загрузки продолжаются с последнего успешно загруженного фрагмента вместо начала с нуля.