0

按照Google Drive REST API 文档,我正在为可恢复的 API 错误实施指数退避策略。如果错误代码是 500 或 403(可能是 429),我想重试我的请求,但我注意到并非所有 403 错误都是可恢复的,所以我只想重试那些在选定列表中有原因的错误. 错误原因未在响应中作为单独的信息提供,但它包含在内容输入流中,我对其进行了解析和处理:

private boolean isRateLimitExceeded(com.google.api.client.http.HttpResponse response) {
    int statusCode = response.getStatusCode();
    if (statusCode == 403) {
        response.getRequest().setParser(Utils.getDefaultJsonFactory().createJsonObjectParser());
        GoogleJsonErrorContainer jsonResponse = response.parseAs(GoogleJsonErrorContainer.class);
        List<ErrorInfo> errors = jsonResponse.getError().getErrors();
        if (errors != null && !errors.isEmpty()) {
            List<String> recoverableErrors = Arrays.asList("limitExceeded", "concurrentLimitExceeded", "rateLimitExceeded", "userRateLimitExceeded", "servingLimitExceeded");
            for (ErrorInfo errorInfo : errors) {
                if (!recoverableErrors.contains(errorInfo.getReason())) {
                    return false;
                }
            }
            return true;
        }
    }
    return false;
}

这工作正常,但会消耗内容。在批处理请求执行过程中,google客户端再次尝试读取和解析内容,发现什么都没有,抛出异常。我尝试标记和重置 response.getContent() 输入流,但 Google 的 HttpResponse 不支持标记。有没有其他方法可以让内容再次可用,或者在不消费的情况下阅读它?

如果重要的话,我使用的是 GoogleNetHttpTransport。

4

1 回答 1

0

我相信这是正确的方法:

private static final String USER_RATE_LIMIT_EXCEEDED_REASON = "userRateLimitExceeded";
private static final String RATE_LIMIT_EXCEEDED_REASON = "rateLimitExceeded";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

private boolean isRateLimitExceeded(HttpResponse response) {
    return response.getStatusCode() == HttpStatusCodes.STATUS_CODE_FORBIDDEN
            && isRateLimitExceeded(GoogleJsonResponseException.from(JSON_FACTORY, response));
}

private boolean isRateLimitExceeded(GoogleJsonResponseException ex) {
    if (ex.getDetails() == null || CollectionUtils.isEmpty(ex.getDetails().getErrors())) {
        return false;
    }
    String reason = ex.getDetails().getErrors().get(0).getReason();
    return RATE_LIMIT_EXCEEDED_REASON.equals(reason) || USER_RATE_LIMIT_EXCEEDED_REASON.equals(reason);
}

另见:https ://www.programcreek.com/java-api-examples/?code=cchabanois/mesfavoris/mesfavoris-master/bundles/mesfavoris.gdrive/src/mesfavoris/gdrive/connection/GDriveBackOffHttpRequestInitializer.java

于 2018-06-03T18:50:11.110 回答