Правильная загрузка файлов с S3 по заранее подписанным URL-адресам

Я пытаюсь реорганизовать существующую базу кода для загрузки нескольких файлов с S3. Если я правильно понимаю документацию, я выполняю слишком много запросов за короткий период времени (1), (2) и (3).

Глядя на документацию AWS SDK, кажется, что существует правильная реализация, как описано по адресу:

Однако пока мне не удалось его использовать. Я проверил страницу примера:

См. раздел «Загрузка или скачивание больших файлов» по ​​адресу:

Похоже, AmazonS3Client не принимает предварительно подписанный URL-адрес в качестве входных данных (только вывод). Та же история с TransferUtility

Кто-нибудь знает, как использовать AWS SDK (или альтернативу C#) для правильной загрузки нескольких файлов из S3 с использованием предварительно подписанных URL-адресов? У меня есть воспроизводимый случай, когда базовая настройка HTTP-клиента не удалась, поскольку количество файлов равно 7000.

Использованная литература:

  1. https://repost.aws/knowledge-center/http-5xx-errors-s3
  2. https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html
  3. https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/retries-timeouts.html

Вы не используете AWS SDK для получения объекта по заранее подписанному URL-адресу. Используйте стандартную библиотеку HTTP. При необходимости реализуйте собственную отсрочку/повторную попытку или найдите библиотеку, которая поможет.

jarmod 06.05.2024 21:41

@jarmod, не хочешь опубликовать реализацию предложения в качестве ответа? Следующий фрагмент кода мне не подходит.

malat 13.05.2024 10:13
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
463
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

вы можете клонировать корзину s3 в свой локальный каталог, который автоматически загрузит ваши видео.

Да, работа с большим количеством файлов, например 7000, с использованием предварительно подписанных URL-адресов с помощью AWS SDK — не самый подходящий подход.

Вы можете использовать HttpClient с Exponential Backoff. Но перед этим вам необходимо будет указать все предварительно подписанные URL-адреса для каждого файла, который вы хотите загрузить.

HttpClient поможет вам отправлять отдельные запросы на загрузку с каждым предварительно подписанным URL-адресом, а механизм повтора Exponential backoff поможет повторить неудачные загрузки.

public async Task DownloadFilesWithBackoff(List<string> preSignedUrls)
{
    int retryCount = 0;
    TimeSpan delay = TimeSpan.FromSeconds(1);

    foreach (string url in preSignedUrls)
    {
        using (var httpClient = new HttpClient())
        {
            HttpResponseMessage response;
            while (true)
            {
                try
                {
                    response = await httpClient.GetAsync(url);
                    response.EnsureSuccessStatusCode();
                    break; // Success, exit loop
                }
                catch (HttpRequestException ex)
                {
                    retryCount++;
                    Console.WriteLine($"Download failed (attempt {retryCount}): {ex.Message}");
                    if (retryCount >= 3) // Adjust retry limit as needed
                    {
                        throw; // Re-throw exception after exceeding retries
                    }
                    await Task.Delay(delay);
                    delay *= 2; // Increase delay for next attempt
                }
            }
            // Process downloaded content from the response
        }
    }
}

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

Я не голосовал против, но предполагаю, что причина, по которой это сделал кто-то другой, заключается в стратегии отсрочки. У .Net Foundation есть проект под названием Polly и его платформа отказов и толерантности с Retry и JittedBacksOffs, которая лучше вашей реализации. например stackoverflow.com/q/62913614/495455 но с алгоритмом JittedBackOff.

Jeremy Thompson 17.05.2024 08:11
Ответ принят как подходящий

ИМО, вам следует контролировать запросы, а не полагаться на стратегии автоматической отсрочки, потому что в этой ситуации вы ЗНАЕТЕ, что они достигнут пределов. https://docs.aws.amazon.com/athena/latest/ug/ Performance-tuning-s3-throttling.html#:~:text=Amazon%20S3%20has%20a%20limit,be%20throttled%20by %20Amazon%20S3. AWS ограничивает вас со скоростью 5500 GET в секунду, что меньше вашего 7000 splat.

Поскольку у вас уже есть заранее назначенные URL-адреса, вам не нужно использовать какой-либо AWS SDK для фактического получения данных. Похоже, вы извлекаете данные из одного клиента, поэтому вам следует просто получать подмножество объектов в пакетном режиме, например. получить 1000 за раз.

Если это распространяется на 7000 отдельных клиентов, обращающихся к одному и тому же объекту S3, вам следует реализовать кэширование CloudFront + и использовать заранее назначенные URL-адреса CloudFront (а не URL-адреса s3) и позволить CF распределять запросы.

Другие вопросы по теме