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;
}
网友评论