尝试使用RESTFul API从Gmail获取消息,我收到此错误消息: 用户速率限制超过
虽然,我实施了限制(1秒内不再有5次获取,当谷歌说1秒内不再有25次通话时)以及当我得到任何异常时也会指数退避,即使这一切我都是仍然得到这个例外。
那么,这可能是什么问题?
由于
答案 0 :(得分:1)
Google API有一个明确定义的配额,以下是适用于Gmail的配额:https://developers.google.com/gmail/api/v1/reference/quota#per-method_quota_usage
这是一个处理配额的小实用程序类(对于单线程,线程安全实现有点复杂):
public class ApilRateLimiter {
private long timeSliceEnd;
private final int quotaPerSecond;
private int quotaRemaining;
public ApilRateLimiter(final int quotaPerSecond) {
this.quotaPerSecond = quotaPerSecond;
this.quotaRemaining = quotaPerSecond;
this.timeSliceEnd = System.currentTimeMillis() + 1_000L;
}
public void reserve(final int quotaReserved) throws InterruptedException {
if (quotaReserved > quotaPerSecond) {
throw new IllegalArgumentException(
"reservation would never be successful as quota requested is greater than quota per second");
}
final long currentTime = System.currentTimeMillis();
if (currentTime >= timeSliceEnd) {
this.timeSliceEnd = currentTime + 1_000L;
this.quotaRemaining = quotaPerSecond - quotaReserved;
} else if (quotaReserved <= quotaRemaining) {
quotaRemaining -= quotaReserved;
} else {
Thread.sleep(timeSliceEnd - currentTime);
reserve(quotaReserved);
}
}
}
以及Gmail配额的定义:
public interface GmailApiLimits {
int QUOTA_PER_SECOND = 250;
int DRAFTS_CREATE = 10;
int DRAFTS_DELETE = 10;
int DRAFTS_GET = 5;
int DRAFTS_LIST = 5;
int DRAFTS_SEND = 100;
int DRAFTS_UPDATE = 15;
int GETPROFILE = 1;
int HISTORY_LIST = 2;
int LABELS_CREATE = 5;
int LABELS_DELETE = 5;
int LABELS_GET = 1;
int LABELS_LIST = 1;
int LABELS_UPDATE = 5;
int MESSAGES_ATTACHMENTS_GET = 5;
int MESSAGES_BATCHDELETE = 50;
int MESSAGES_DELETE = 10;
int MESSAGES_GET = 5;
int MESSAGES_IMPORT = 100;
int MESSAGES_INSERT = 25;
int MESSAGES_LIST = 5;
int MESSAGES_MODIFY = 5;
int MESSAGES_SEND = 100;
int MESSAGES_TRASH = 5;
int MESSAGES_UNTRASH = 5;
int STOP = 50;
int THREADS_DELETE = 20;
int THREADS_GET = 10;
int THREADS_LIST = 10;
int THREADS_MODIFY = 10;
int THREADS_TRASH = 10;
int THREADS_UNTRASH = 10;
int WATCH = 100;
}
你这样使用它:
this.apiRateLimiter = new ApilRateLimiter(GmailApiLimits.QUOTA_PER_SECOND);
...
apiRateLimiter.reserve(GmailApiLimits.MESSAGES_LIST);
gmailApi.users().messages().list("me")...execute();
...
apiRateLimiter.reserve(GmailApiLimits.MESSAGES_GET);
gmailApi.users().messages().get("me"...execute();
...
基本上,在拨打Gmail API之前,请致电reserve()
。如果第二个剩余配额,则保留立即返回,否则它会一直休眠直到第二个结束。