简体   繁体   中英

Gmail API Users.Messages.get throws User Rate Limit Exceeded

Trying to get message from the Gmail using RESTFul API and I'm getting this error : User Rate Limit Exceeded

While, I'm implemented throttling (no more 5 gets in 1 sec, when google says that no more 25 calls in 1 sec) and also exponential backoff when I'm getting any exception and even with all this I'm still getting this exception.

So, what could be the issue here ?

Thanks

There is a well defined quota for Google APIs, here is the one for Gmail: https://developers.google.com/gmail/api/v1/reference/quota#per-method_quota_usage

Here is a small utility class to handle the quota (for single threads, the thread safe implementation is a bit more complex):

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

and the definition for the Gmail quotas:

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

You use it like so:

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();
...

Basically, you call reserve() before you make a Gmail API call. If there is quota left for the second, reserve returns right away, otherwise it sleeps until the second is over.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM