我尝试过静态睡眠、计数请求和做简单数学的简单解决方案,但它们往往非常不准确、不可靠,并且通常会引入更多睡眠,而这在他们本来可以工作时是必需的。您想要的是仅在您接近速率限制时才开始发出相应的睡眠。
从previous problem 提出我的解决方案以获得那些甜蜜、甜蜜的互联网点:
我使用了一些数学来计算出一个函数,该函数会在给定请求的正确时间总和内休眠,并允许我在最后以指数方式增加它。
如果我们将睡眠表示为:
y = e^( (x-A)/B )
其中A 和B 是控制曲线形状的任意值,那么从0 到N 请求的所有睡眠M 的总和将是:
M = 0∫N e^( (x-A)/B ) dx
这相当于:
M = B * e^(-A/B) * ( e^(N/B) - 1 )
关于 A 可以解为:
A = B * ln( -1 * (B - B * e^(N/B)) / M )
虽然求解 B 会更有用,因为指定 A 可以让您定义图形急剧上升的点,该解决方案在数学上很复杂,我自己或找到可以的人其他。
/**
* @param int $period M, window size in seconds
* @param int $limit N, number of requests permitted in the window
* @param int $used x, current request number
* @param int $bias B, "bias" value
*/
protected static function ratelimit($period, $limit, $used, $bias=20) {
$period = $period * pow(10,6);
$sleep = pow(M_E, ($used - self::biasCoeff($period, $limit, $bias))/$bias);
usleep($sleep);
}
protected static function biasCoeff($period, $limit, $bias) {
$key = sprintf('%s-%s-%s', $period, $limit, $bias);
if( ! key_exists($key, self::$_bcache) ) {
self::$_bcache[$key] = $bias * log( -1 * ( ($bias - $bias * pow(M_E, $limit/$bias)) / $period ) );
}
return self::$_bcache[$key];
}
经过一番修改,我发现B = 20 似乎是一个不错的默认值,尽管我没有数学基础。 某事斜率mumble mumble指数bs bs。
另外,如果有人想为我解 B 的方程式 I've got a bounty up on math.stackexchange。
尽管我认为我们的情况略有不同,因为我的 API 提供者的响应都包括可用 API 调用的数量,以及仍然保留在窗口内的数量。您可能需要额外的代码来跟踪这一点。