Как ограничить скорость вызовов API Google Диска?

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

Я врезаюсь в стену так же, как другие писали о переполнении стека: Google Диск Ограничения по скорости просмотра файлов API.

Экспоненциальный откат имеет для меня большой смысл, я просто не знаю, как это реализовать.

Любое понимание, которое я смогу получить, было бы невероятно полезным. Даже просто "начать с ..." было бы здорово!

Я добавил метод, над которым работаю, ниже. Auth и все работает нормально, дело только в получении ошибки userRateLimitExceeded.

Любая помощь была бы фантастической и очень ценилась бы.

Спасибо!

/**
 * Download all of the shared images.
 *
 * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
 */
function downloadImages(auth) {
  const gDrive = google.drive({
    version: 'v3',
    auth: auth
  });

  gDrive.files.list({
    q: 'sharedWithMe = true and mimeType = "image/jpeg"'
  }, (err, resp) => {
    if(err) {
      console.log('The API returned an error: ' + err);
      return;
    }

    if(!resp.files.length) {
      console.error('No files found.');
    } else {
      // Remove existing images.
      // removeImages();

      _.each(resp.files, (file) => {
        if(fs.existsSync(IMAGE_DIR + file.name)) {
          return;
        }

        gDrive.files.get({
          fileId: file.id
        })
        .on('end', () => {
          console.log(chalk.green(file.name + ' successfully downloaded.'));
        })
        .on('error', (err) => {
          console.log(err);
        })
        .pipe(fs.createWriteStream(IMAGE_DIR + file.name));
      });
    }
  });
}

РЕДАКТИРОВАТЬ: я изучал пакетную обработку, но полагаю, что google-api-nodejs-client не поддерживает пакеты. Я попробовал стороннюю библиотеку под названием «Бэтчелор». До сих пор не могу заставить его работать, хоть убей. :(


comment
Что делает gDrive.fkiles.get(), когда у вас ограничена скорость? У вас есть определенная ошибка в обработчике событий .on('error', ...), которую вы можете обнаружить? Если да, то что это за конкретная ошибка? По сути, если вы можете помочь нам узнать, как определить, когда ваша скорость ограничена, мы можем помочь с кодом, чтобы справиться с этим.   -  person jfriend00    schedule 18.12.2016
comment
@ jfriend00 - Не похоже, что до обработчика ошибок дошло. Он просто вернется с объектом ошибки, говоря userRateLimitExceeded или что-то в этом роде. И я говорю, что это не дошло до обработчика ошибок, потому что, если бы я сделал что-то вроде console.error('error', error), я бы вообще не увидел свою метку журнала. :(   -  person Will    schedule 18.12.2016


Ответы (3)


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

Вы можете потрогать код на https://github.com/pinoyyid/ngDrive/blob/master/src/http_s.ts Это сервис Angular 1, который обрабатывает идиосинкразии GDrives, включая 403. Он выполняет это, помещая запросы во внутреннюю очередь, а затем у меня есть процесс, который удаляет элементы из очереди с переменной скоростью, чтобы максимизировать пропускную способность, но сводит к минимуму количество попыток 403 и повторных попыток оператора.

Пакетирование еще больше усугубляет ситуацию, так что не идите по этому пути. Ограничивающим фактором является не скорость HTTP-запросов, а скорость запросов к внутренним системам GDrive. Пакет запросов запускается в GDrive в быстрой последовательности, операционная система с большей вероятностью вызовет ошибку 403.

person pinoyyid    schedule 18.12.2016
comment
Оцените ответ. К сожалению, мне не удалось получить простой пример локальной работы ngDrive. Что-то про 401. Это ошибка. Ошибка: invalid_client нет зарегистрированного происхождения. Думаю, именно здесь я отказываюсь от этой идеи. : / - person Will; 18.12.2016
comment
что 401 - это просто конфиг. Вам необходимо: 1 / создать идентификатор клинета в консоли API, 2 / настроить его в своем приложении, 3 / обслуживать приложение с одного из авторизованных URL-адресов, которые вы указали на шаге 1. - person pinoyyid; 19.12.2016

Основываясь на этой документации, ошибка error 403 или userRateLimitExceeded, которая вы получили означает, что достигнут предел количества пользователей в консоли разработчика.

Обратите внимание, что Drive API имеет:

  • Ежедневная квота 1000000000 запросов в день
  • Ежедневная квота вежливости в секунду 100 запросов в секунду
  • Ограничение на пользователя: 10 запросов в секунду на пользователя.

Вот скриншот квоты по умолчанию для Drive API.

введите здесь описание изображения

Итак, предлагаемые действия для вашей ошибки:

  • Увеличьте квоту на пользователя в проекте Developer Console. (Используйте эту ссылку, чтобы запросить дополнительную квоту)

  • Если один пользователь делает много запросов от имени многих пользователей домена Google Apps, рассмотрите возможность Учетная запись службы с делегированием полномочий (установка параметра quotaUser ).

  • Используйте экспоненциальную отсрочку.

Для получения дополнительной информации ознакомьтесь с этими вопросами SO:

person KENdi    schedule 18.12.2016
comment
Ограничение на пользователя 10 запросов в секунду на пользователя неверно. Регулирование скорости более сложное, чем это, и не документировано публично. - person pinoyyid; 18.12.2016
comment
Проверьте консоль разработчика, вы увидите, что User - 100s имеет квоту по умолчанию 1000. Это означает, что у вас есть ограничение на 10 запросов в секунду на пользователя. Посмотрите скриншот, который я предоставил. - person KENdi; 19.12.2016
comment
Это совсем не значит. Есть много разных ограничений. Чаще всего люди спотыкаются о регулировании скорости, которое работает с алгоритмом токена / корзины, который не опубликован. - person pinoyyid; 19.12.2016

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

Я использовал сценарий, который отправляет пакет из 10 запросов каждые 1,3 секунды, эти сценарии работают нормально.

Однако при отправке пакета из 100 запросов в течение 13 секунд возникают 403 ошибки.

Итак, вывод: следите за посекундным, а не 100-секундным ограничением.

person Hilmi Hamdan    schedule 23.08.2019