4

ゴミ箱に移動されていないすべてのファイルを要求するドライブアプリケーションがあります。ただし、読み取りタイムアウトを伴うIOexceptionをスローする場合があります。これを回避する方法はありますか?

これは私が得るエラーです:

エラーが発生しました:java.net.SocketTimeoutException:読み取りがタイムアウトしました

たぶん、私の指数バックオフは間違って実装されています。

ファイルを取得するために使用するコードは次のとおりです。

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;
}
4

3 に答える 3

8

私も数日前に同じ経験をしました。私の質問に対する答えはここにありました。https://code.google.com/p/google-api-java-client/wiki/FAQ . ドライブのインスタンスを作成するときに、setHttpRequestInitializer メソッドを呼び出し、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();
于 2014-05-18T00:05:57.783 に答える
3

指数関数的バックオフは、再試行の機会を増やすための方法にすぎません。うまくいけば、次回はより良くなるでしょう。しかし、それは問題の根本に対処していませんでした。

最大結果を 1000 に設定していることに気付きました。通常、読み取りタイムアウトはサーバー側での長い処理時間が原因であることを考慮すると、この数値を 500 または 200 に減らすことをお勧めします。

最大結果数 1000 を使用して変更をフェッチしているときに同じ問題が発生しました。サイズを 200 または 500 に変更すると、スムーズに動作します。

許容される最大数はサーバーの状況に関連し、動的に変化するため、最大結果数を自動的に更新する指数バックオフ戦略を設計することもできます。たとえば、1000 から開始し、エラーが発生した場合は 500 に変更し、まだエラーがある場合は 200 に変更します。しばらくエラーが発生しない場合は、再び 500 に増やします。

これが役立つことを願って〜

于 2013-12-27T17:24:37.480 に答える
1

指数バックオフは、タイムアウトがある場合に取得できない GoogleJsonException をキャッチした場合にのみトリガーされます。指数バックオフでも SocketTimeoutException をキャッチできます

于 2012-10-23T09:53:33.283 に答える