Ускоряйте загрузку файлов в любую точку мира с R2 Local Uploads

Сегодня мы запускаем Локальные загрузки для R2 в открытом бета-режиме. При включенной функции Локальных загрузок данные объекта сначала автоматически записываются в хранилище, близкое к клиенту, а затем асинхронно копируются туда, где находится бакет. Данные становятся доступными немедленно и сохраняют строгую согласованность. Загрузки ускоряются, а данные становятся глобальными.

Для многих приложений производительность должна быть глобальной. Например, пользователи загружают медиаконтент из разных регионов или устройства отправляют логи и телеметрию со всего мира. Но ваши данные должны где-то храниться, а это означает, что загрузкам издалека приходится преодолевать большое расстояние до вашего бакета.

R2 — это объектное хранилище, построенное на глобальной сети Cloudflare. Из коробки оно автоматически кэширует данные объектов по всему миру для быстрого чтения где угодно — всё это при сохранении строгой согласованности и нулевых плат за исходящий трафик. Это происходит в фоновом режиме, независимо от того, используете ли вы S3 API, Workers Bindings или обычный HTTP. А теперь с Локальными загрузками и чтение, и запись могут быть быстрыми из любой точки мира.

Попробуйте сами в этом демо, чтобы увидеть преимущества Локальных загрузок.

Готовы попробовать? Включите Локальные загрузки в Панели управления Cloudflare в настройках вашего бакета или с помощью одной команды Wrangler для существующего бакета.

npx wrangler r2 bucket local-uploads enable [BUCKET]

Снижение общего времени выполнения запросов на 75% для глобальных загрузок

Локальные загрузки ускоряют запросы на загрузку (например, PutObject, UploadPart). Как в наших закрытых бета-тестах с клиентами, так и в синтетических тестах мы наблюдали снижение времени до последнего байта (TTLB) до 75%, когда запросы на загрузку выполнялись в регионе, отличном от региона бакета. В этих результатах TTLB измеряется с момента получения R2 запроса на загрузку до момента возврата R2 ответа 200.

В наших синтетических тестах мы измерили влияние Локальных загрузок, используя синтетическую нагрузку для имитации процесса межрегиональной загрузки. Мы развернули тестового клиента в Западной Северной Америке и настроили бакет R2 с указанием местоположения для Азиатско-Тихоокеанского региона. Клиент выполнял около 20 запросов PutObject в секунду в течение 30 минут для загрузки объектов размером 5 МБ.

Следующий график сравнивает p50 (или медианные) показатели TTLB для этих запросов, показывая разницу в длительности запроса на загрузку — сначала без Локальных загрузок (TTLB около 2 с), а затем с включенными Локальными загрузками (TTLB около 500 мс):

Improve global upload performance with R2 Local Uploads

Как это работает: проблема расстояния

Чтобы понять, как Локальные загрузки могут улучшить запросы на загрузку, давайте сначала посмотрим на принцип работы R2. Архитектура R2 состоит из нескольких компонентов, включая:

  • R2 Gateway Worker: Точка входа для всех API-запросов, которая обрабатывает логику аутентификации и маршрутизации. Он развернут по всей глобальной сети Cloudflare через Cloudflare Workers.

  • Служба метаданных объектов на Durable Objects: Распределенный уровень, построенный на Durable Objects, используемый для хранения и управления метаданными объектов (например, ключ объекта, контрольная сумма).

  • Распределенная инфраструктура хранения: Базовая инфраструктура, которая постоянно хранит зашифрованные данные объектов.

Без Локальных загрузок вот что происходит при загрузке объектов в ваш бакет: Сначала запрос принимается R2 Gateway, близким к пользователю, где происходит аутентификация. Затем, когда клиент передает байты данных объекта, данные шифруются и записываются в инфраструктуру хранения в регионе размещения бакета. После завершения этого процесса Gateway обращается к Службе метаданных для публикации метаданных объекта и возвращает клиенту успешный ответ после их фиксации.

Если клиент и бакет находятся в разных регионах, в процесс загрузки байтов данных объекта может быть внесена большая вариативность из-за большего расстояния, которое должен преодолеть запрос. Это может привести к более медленным или менее надежным загрузкам.

Improve global upload performance with R2 Local Uploads

Клиент загружает данные из Восточной Северной Америки в бакет в Восточной Европе без включенных Локальных загрузок.

Теперь, когда вы выполняете запрос на загрузку в бакет с включенными Локальными загрузками, обрабатываются два случая:

  1. Клиент и регион бакета находятся в одном регионе

  2. Клиент и регион бакета находятся в разных регионах

В первом случае R2 следует обычному процессу, при котором данные объекта записываются в инфраструктуру хранения вашего бакета. Во втором случае R2 записывает данные в инфраструктуру хранения, расположенную в регионе клиента, при этом по-прежнему публикуя метаданные объекта в регионе бакета.

Важно, что объект становится доступным сразу после завершения начальной записи. Он остается доступным на протяжении всего процесса репликации — не существует периода ожидания завершения фоновой репликации, прежде чем объект можно будет прочитать.

Improve global upload performance with R2 Local Uploads

Клиент загружает данные из Восточной Северной Америки в бакет в Восточной Европе с включенными Локальными загрузками.

Обратите внимание, что это относится к бакетам без юрисдикционных ограничений. Локальные загрузки недоступны для бакетов с включенными юрисдикционными ограничениями (например, ЕС, FedRAMP).

Когда использовать Локальные загрузки

Локальные загрузки созданы для рабочих нагрузок, которые получают много запросов на загрузку из географических регионов, отличных от местоположения вашего бакета. Эта функция идеальна, когда:

  • Ваши пользователи распределены по всему миру

  • Производительность и надежность загрузки критически важны для вашего приложения

  • Вы хотите оптимизировать производительность записи без изменения основного местоположения вашего бакета

Чтобы понять географическое распределение источников ваших запросов на чтение и запись, вы можете посетить Панель управления Cloudflare, перейти на страницу метрик вашего бакета R2 и просмотреть график распределения запросов по регионам.

Improve global upload performance with R2 Local Uploads

Как мы создали Локальные загрузки

При Локальных загрузках данные объекта записываются близко к клиенту, а затем копируются в регион бакета в фоновом режиме. Мы называем эту задачу копирования задачей репликации.

Учитывая эти задачи репликации, нам понадобился асинхронный компонент для их обработки, что является отличным вариантом использования для Cloudflare Queues. Очереди позволяют нам контролировать скорость обработки задач репликации и предоставляют встроенные возможности обработки сбоев, такие как повторные попытки и очереди недоставленных сообщений. В данном случае R2 распределяет задачи репликации по нескольким очередям в каждом регионе хранения.

Публикация метаданных и планирование репликации

При публикации метаданных объекта с включенными Локальными загрузками мы выполняем три операции атомарно:

  1. Сохраняем метаданные объекта

  2. Создаем ключ ожидающей реплики, который отслеживает, какие репликации еще необходимо выполнить

  3. Создаем маркер задачи репликации с ключом по временной метке, который контролирует, когда задача должна быть отправлена в очередь

Ключ ожидающей реплики содержит полный план репликации: количество задач репликации, из какого исходного местоположения читать, в какое целевое местоположение записывать, режим и приоритет репликации, а также следует ли удалять исходные данные после успешной репликации.

Это дает нам гибкость в перемещении данных объекта. Например, перемещение данных на большие географические расстояния обходится дорого. Мы могли бы попытаться переместить все реплики как можно быстрее, обрабатывая их параллельно, но это привело бы к большим затратам и нагрузке на сетевую инфраструктуру. Вместо этого мы минимизируем количество межрегиональных перемещений данных, сначала создавая одну реплику в целевом регионе бакета, а затем используя эту локальную копию для создания дополнительных реплик внутри региона бакета.

Improve global upload performance with R2 Local Uploads

Фоновый процесс периодически сканирует маркеры задач репликации и отправляет их в одну из очередей, связанных с регионом-приемником хранилища. Маркеры гарантируют доставку в очередь как минимум один раз — если отправка в очередь завершается сбоем или процесс аварийно завершается, маркер сохраняется, и задача будет повторена при следующем сканировании. Это также позволяет нам обрабатывать репликации в разное время и ставить в очередь только валидные задачи. Как только задача репликации попадает в очередь, она готова к обработке.

Improve global upload performance with R2 Local Uploads

Асинхронная репликация: Модель Pull

В качестве потребителя очереди мы выбрали модель pull, в которой централизованный сервис опроса (polling service) забирает задачи из региональных очередей и направляет их на выполнение в Gateway Worker.

Improve global upload performance with R2 Local Uploads

Вот как это работает:

  1. Сервис опроса забирает задачи из региональной очереди: Сервис-потребитель опрашивает региональную очередь на наличие задач репликации. Затем он группирует задачи в батчи единообразного размера на основе объема перемещаемых данных.

  2. Сервис опроса направляет задачи в Gateway Worker: Сервис-потребитель отправляет задание на репликацию в Gateway Worker.

  3. Gateway Worker выполняет репликацию: Воркер считывает данные объекта из исходного местоположения, записывает их в место назначения и обновляет метаданные в Durable Object, при необходимости помечая исходное местоположение для сборки мусора.

  4. Gateway Worker сообщает о результате: По завершении воркер возвращает результат сервису опроса, который подтверждает очереди успешное выполнение или сбой задачи.

Используя этот подход с моделью pull, мы обеспечиваем стабильность и эффективность процесса репликации. Сервис может динамически регулировать свой темп в зависимости от состояния системы в реальном времени, гарантируя безопасную репликацию данных между регионами.

Попробуйте сами

Функция Local Uploads уже доступна в открытой бета-версии. За её подключение не взимается дополнительная плата. Запросы на загрузку, выполняемые с этой функцией, влекут стандартные затраты на операции класса A, такие же, как и запросы на загрузку без Local Uploads.

Чтобы начать работу, перейдите в Cloudflare Dashboard в настройках вашего бакета и найдите карточку Local Uploads для активации, или просто выполните следующую команду с помощью Wrangler, чтобы включить Local Uploads для бакета.

npx wrangler r2 bucket local-uploads enable [BUCKET]

Включение функции Local Uploads для бакета происходит бесшовно: существующие загрузки завершатся в штатном режиме, и трафик не будет прерван.