一个漏桶的基本实现,它的想法是你叫它说,我将允许,例如,5次登录尝试每60秒。
//Leaky Bucket algorithm with chrono
class RateController {
int n;
std::chrono::steady_clock::duration interval;
int cnt;
std::chrono::time_point<std::chrono::steady_clock> last;
public:
RateController(int limit, int seconds) :
n(limit), interval(std::chrono::seconds(seconds/limit)), cnt(0) {}
bool ok() {
auto t = std::chrono::steady_clock::now();
if (cnt) {
cnt -= (t - last) / interval;
if (cnt < 0) cnt = 0;
if (cnt >= n) return false;
}
++cnt;
last = t;
return true;
}
};发布于 2022-03-28 21:16:19
的时钟创建类型别名
如果您为时钟创建一个类型别名,就会变得更易于维护和编写,如下所示:
using clock = std::chrono::steady_clock;这样,你就可以写:
clock::duration interval;
clock::time_point last;
...
auto t = clock::now();使用无符号类型。
我建议对计数器使用无符号类型,因为它们不应该是负的。为了避免计数器泄漏,请写:
cnt -= std::min(cnt, (t - last) / interval);std::chrono::duration的形式传递间隔
不要强迫调用方将持续时间作为描述秒的整数传递,然后必须自己将其转换为std::chrono::duration类型,而是考虑将构造函数的参数seconds更改为clock::duration类型。然后调用方可以传入它喜欢的任何std::chrono::duration。
表达式seconds / limit将计算为0如果limit > seconds。这是有问题的,因为它将导致ok()中的除数为零。我将完全避免除法,并让interval表示对ok()的最多limit调用将返回true的间隔。为了泄密,你只需写:
cnt -= std::min(cnt, (t - last) * n / interval);有些事情是不必要地缩略的。而不是cnt,而是编写count。不要编写n,而是编写max_count或limit,就像在构造函数中那样。而不是t,写now或current_time。这只是需要输入的几个字符,但是当您忘记了实现的细节时,它将使任何阅读它的人(包括您自己)更加清楚。
https://codereview.stackexchange.com/questions/275307
复制相似问题