Как избежать таймаута чтения при запросе всех файлов? (Google drive api)
У меня есть приложение для дисков, которое запрашивает все файлы, которые не уничтожены. Но иногда он выдает исключение IOexception с таймаутом чтения. Есть ли способ избежать этого?
Это ошибка, которую я получаю:
Произошла ошибка: java. net. SocketTimeoutException: Read timed out
Возможно, мой экспоненциальный откат реализован неправильно.
Вот код, который я использую для получения файлов:
private static List<File> retrieveAllNoTrashFiles(Drive service) throws IOException, InterruptedException {
List<File> result = new ArrayList<File>();
Files.List request = service.files().list().setQ("trashed = false").setMaxResults(1000);
do {
try {
FileList files =executeRequest(service,request);
result.addAll(files.getItems());
request.setPageToken(files.getNextPageToken());
} catch (IOException e) { //here I sometimes get the read timeout
System.out.println("An error occurred: " + e);
request.setPageToken(null);
}
} while (request.getPageToken() != null
&& request.getPageToken().length() > 0);
return result;
}
private static FileList executeRequest(Drive service,Files.List request) throws IOException, InterruptedException {
Random randomGenerator = new Random();
for (int n = 0; n < 5; ++n) {
try {
return(request.execute());
} catch (GoogleJsonResponseException e) {
if (e.getDetails().getCode() == 403
&& (e.getDetails().getErrors().get(0).getReason().equals("rateLimitExceeded")
|| e.getDetails().getErrors().get(0).getReason().equals("userRateLimitExceeded"))) {
// Apply exponential backoff.
Thread.sleep((1 << n) * 1000 + randomGenerator.nextInt(1001));
}
//else {
// Other error, re-throw.
// throw e;
// }
}
}catch(SocketTimeoutException e){
Thread.sleep((1 << n) * 1000 + randomGenerator.nextInt(1001));
}
System.err.println("There has been an error, the request never succeeded.");
return null;
}
3 ответа:
Экспоненциальный откат срабатывает только тогда, когда вы ловите исключение GoogleJsonException, которое вы не получаете, когда у вас есть тайм-аут. Вы можете поймать SocketTimeoutException также в экспоненциальной задержки
У меня был такой же опыт несколько дней назад. Ответ на мой вопрос был найден здесь. https://code.google.com/p/google-api-java-client/wiki/FAQ при создании экземпляра диска можно вызвать метод setHttpRequestInitilalizer, передать новый экземпляр HttpRequestInitializer в качестве аргумента и реализовать метод initialize. Там вы можете увеличить значение ReadTimeout и ConnectionTimeout.
Вот пример кода:
Drive drive = new Drive.Builder(this.httpTransport, this.jsonFactory, this.credential).setHttpRequestInitializer(new HttpRequestInitializer() { @Override public void initialize(HttpRequest httpRequest) throws IOException { credential.initialize(httpRequest); httpRequest.setConnectTimeout(300 * 60000); // 300 minutes connect timeout httpRequest.setReadTimeout(300 * 60000); // 300 minutes read timeout } }).setApplicationName("My Application").build();
Экспоненциальный откат-это просто способ дать вам больше шансов повторить его, надеюсь, в следующий раз это будет лучше. Но это не касалось корня проблемы.
Я заметил, что вы установили максимальный результат в 1000. Учитывая, что тайм-аут чтения обычно вызван длительным временем обработки на стороне сервера, я бы предложил вам уменьшить это число до 500 или 200.
Я столкнулся с теми же проблемами, когда выбирал изменения с помощью max result count 1000. Когда я изменю размер на 200 или 500, это работает гладко.
Поскольку допустимое максимальное число связано с ситуацией на сервере и изменяется динамически, можно также разработать стратегию экспоненциального отката для автоматического обновления максимального количества результатов. Например, начните с 1000, если ошибка обнаружена, то измените на 500, если все еще есть ошибка, то измените на 200. Если нет ошибки в течение некоторого времени, то снова увеличьте до 500.
Надеюсь, это поможет~