美文网首页
DropboxRateLimiter 源码分析

DropboxRateLimiter 源码分析

作者: 付凯强 | 来源:发表于2024-02-18 23:21 被阅读0次

DropboxRateLimiter用来限制添加到dropbox中的错误的速度,核心函数为shouldRateLimit,核心数据结构为mErrorClusterRecords。

清理过期数据

当有错误发生,需要写入dropbox时,会对mErrorClusterRecords的过期数据进行清理
清理频率:上次清理距离现在已有30分钟
何为过期:数据已经存放大于30分钟

    // Remove expired records if enough time has passed since the last cleanup.
    maybeRemoveExpiredRecords(now);
    private void maybeRemoveExpiredRecords(long now) {
        if (now - mLastMapCleanUp <= RATE_LIMIT_BUFFER_EXPIRY) return;

        for (int i = mErrorClusterRecords.size() - 1; i >= 0; i--) {
            if (now - mErrorClusterRecords.valueAt(i).getStartTime() > RATE_LIMIT_BUFFER_EXPIRY) {
                mErrorClusterRecords.removeAt(i);
            }
        }

        mLastMapCleanUp = now;
    }

存储新数据

以错误类型+进程名称为key,以错误的发生时间和累计发生次数为值(ErrorRecord)存储到mErrorClusterRecords,此时不进行拦截,并返回RateLimitResult对象
RateLimitResult对象包含两个信息:不拦截(mShouldRateLimit)以及被拦截的次数为0(mDroppedCountSinceRateLimitActivated)

    String errorKey(String eventType, String processName) {
        return eventType + processName;
    }
    ErrorRecord errRecord = mErrorClusterRecords.get(errorKey(eventType, processName));
    if (errRecord == null) {
        errRecord = new ErrorRecord(now, 1);
        mErrorClusterRecords.put(errorKey(eventType, processName), errRecord);
        return new RateLimitResult(false, 0);
    }

重置数据

相同进程的相同错误发生时,后一个如果比前一个的发生时间大于10分钟(RATE_LIMIT_BUFFER_DURATION),会重置此错误的时间和次数,此时不进行拦截,并返回RateLimitResult对象
RateLimitResult对象包含两个信息:不拦截(mShouldRateLimit)以及被拦截的次数(mDroppedCountSinceRateLimitActivated)

    if (now - errRecord.getStartTime() > RATE_LIMIT_BUFFER_DURATION) {
        final int errCount = recentlyDroppedCount(errRecord);
        errRecord.setStartTime(now);
        errRecord.setCount(1);

        return new RateLimitResult(false, errCount);
    }

累加数据

如果相同进程的相同错误发生时,后一个如果比前一个的发生时间不大于10分钟(RATE_LIMIT_BUFFER_DURATION),会进行错误累加,此时不进行拦截,并返回RateLimitResult对象
RateLimitResult对象包含两个信息:不拦截(mShouldRateLimit)以及被拦截的次数为0(mDroppedCountSinceRateLimitActivated)

    errRecord.incrementCount();
    return new RateLimitResult(false, 0);

拦截写入

当相同进程的相同错误,在10分钟之内发生次数超过6次(RATE_LIMIT_ALLOWED_ENTRIES),此时会进行拦截,并返回RateLimitResult对象。
RateLimitResult对象包含两个信息:拦截(mShouldRateLimit)以及被拦截的次数(mDroppedCountSinceRateLimitActivated)

    if (errRecord.getCount() > RATE_LIMIT_ALLOWED_ENTRIES) {
        return new RateLimitResult(true, recentlyDroppedCount(errRecord));
    }

拦截次数的计算规则

被拦截次数的计算规则如下:错误的累加发生次数超过RATE_LIMIT_ALLOWED_ENTRIES的部分为被拦截次数,如果不超过,拦截次数为0

    /**
     * Returns the number of entries of a certain type and process that have recenlty been
     * dropped. Resets every RATE_LIMIT_BUFFER_DURATION if events are still actively created or
     * RATE_LIMIT_BUFFER_EXPIRY if not. */
    private int recentlyDroppedCount(ErrorRecord errRecord) {
        if (errRecord == null || errRecord.getCount() < RATE_LIMIT_ALLOWED_ENTRIES) return 0;
        return errRecord.getCount() - RATE_LIMIT_ALLOWED_ENTRIES;
    }

相关文章

网友评论

      本文标题:DropboxRateLimiter 源码分析

      本文链接:https://www.haomeiwen.com/subject/qwzpadtx.html