Мультипартовая (составная) загрузка — способ отправить большой объект в хранилище не единым потоком, а частями, которые передаются независимо и собираются в один объект на стороне сервиса. Ниже — как устроен механизм и о чём важно помнить при работе с ним.
Как это устроено
Загрузка состоит из трёх этапов:
- Инициализация. Клиент сообщает хранилищу, что начинает составную загрузку. В ответ приходит идентификатор UploadId, который связывает все последующие операции. На этом же этапе объекту задаются метаданные и тип содержимого.
- Передача частей. Файл разбивается на части, каждая отправляется отдельным запросом со своим порядковым номером. На каждую часть хранилище возвращает контрольную сумму ETag. Части передаются параллельно и в произвольном порядке.
- Завершение. Клиент отправляет список номеров частей и их контрольных сумм, после чего хранилище собирает из них единый объект. Только с этого момента объект появляется в бакете и становится доступен для чтения.
Что это даёт
- Устойчивость к обрывам связи. Сбой при передаче затрагивает только одну часть — её достаточно отправить заново, не начиная загрузку файла целиком.
- Скорость. Части передаются параллельно, что позволяет полнее использовать пропускную способность канала.
- Гибкость по времени. Передачу можно начать, не дожидаясь, пока файл будет сформирован полностью, и продолжить позже: незавершённая загрузка сохраняется в хранилище.
Когда она применяется
Отдельно включать составную загрузку обычно не нужно — клиенты делают это автоматически. AWS CLI переключается на неё, когда размер файла превышает установленный порог; порог и размер части задаются параметрами профиля multipart_threshold и multipart_chunksize. S3 Browser использует составную загрузку по умолчанию, размер части задаётся в настройках клиента и по умолчанию равен 8 МБ.
Ручное управление этапами через вызовы S3 API нужно в более узких сценариях: когда части формируются разными процессами, загружаются с разных машин или требуется собственная логика повторных попыток.
Ограничения
| Параметр | Значение по спецификации S3 |
|---|---|
| Минимальный размер части | 5 МБ (ограничение не распространяется на последнюю часть) |
| Максимальный размер части | 5 ГБ |
| Максимальное число частей в одной загрузке | 10 000 |
| Максимальный размер объекта | 5 ТБ |
| Рекомендуемый порог перехода на составную загрузку | от 100 МБ |
Предел в 10 000 частей стоит держать в голове при настройке размера части: при части в 8 МБ максимальный размер файла составит около 80 ГБ. Для файлов большего объёма размер части нужно увеличивать.
Незавершённые загрузки занимают место
Если загрузка начата, но не завершена — процесс прерван, скрипт упал, пропала связь, — уже переданные части остаются в хранилище. Они не образуют объект и не отображаются в обычном списке файлов, но занимают место и тарифицируются.
Важно! Незавершённая загрузка не истекает сама по себе. Она хранится сколь угодно долго, пока её не завершат, не прервут явной командой или не удалит правило жизненного цикла.
Именно поэтому «зависшие» загрузки — одна из двух основных причин расхождения между ожидаемым и фактическим объёмом бакета. Вторая — накопленные версии объектов (см. «Что такое версионирование в S3»).
Найти незавершённые загрузки можно командой:
aws s3api list-multipart-uploads \
--bucket <ИМЯ_БАКЕТА> \
--profile rtcloud \
--endpoint-url https://s3-msk2.rtcloud.ru
В ответе для каждой загрузки будут имя объекта Key, идентификатор UploadId и дата начала. Прервать конкретную загрузку и освободить место:
aws s3api abort-multipart-upload \
--bucket <ИМЯ_БАКЕТА> \
--key <ИМЯ_ОБЪЕКТА> \
--upload-id <ИДЕНТИФИКАТОР_ЗАГРУЗКИ> \
--profile rtcloud \
--endpoint-url https://s3-msk2.rtcloud.ru
В примерах используется профиль rtcloud и эндпоинт https://s3-msk2.rtcloud.ru — подставляйте свои значения (см. «Как создать профиль подключения к S3 в AWS CLI»).
Как не заниматься этим вручную
Добавьте в политику жизненного цикла бакета правило AbortIncompleteMultipartUpload со сроком 7 дней (см. «Как настроить правило жизненного цикла через AWS CLI»). Этого достаточно, чтобы вернуться и возобновить прерванную загрузку, и мало, чтобы забытые части копились месяцами.
Такое правило стоит добавить на все бакеты, куда регулярно загружаются большие файлы: резервные копии, образы, медиаархивы.
Смотрите также:
к Работе с S3 RTCloud