当前位置:  开发笔记 > 编程语言 > 正文

如何限制网站的API用户?

如何解决《如何限制网站的API用户?》经验,为你挑选了2个好方法。

我的网站的合法用户偶尔会通过API请求敲击服务器,从而导致不良结果.我想建立一个限制,不过每5秒说一次API调用或每分钟n次调用(还没有弄清楚确切的限制).我显然可以在数据库中记录每个API调用,并对每个请求进行计算以查看它们是否超出限制,但是每个请求的所有额外开销都将失去目的.我可以用什么其他资源不足的方法来制定限制?我正在使用PHP/Apache/Linux,它的价值.



1> scotts..:

好吧,如果没有对服务器的任何写入,就没有办法做我的要求,但我至少可以消除每个请求的记录.一种方法是使用"漏桶"限制方法,其中它仅跟踪最后一个请求($last_api_request)和时间帧($minute_throttle)的请求数/限制的比率.漏桶永远不会重置其计数器(不同于每小时重置的Twitter API的节流),但如果存储桶已满(用户达到限制),则他们必须等待n几秒钟才能使存储桶清空一点,然后再发出另一个请求.换句话说,它就像一个滚动限制:如果在时间范围内有先前的请求,它们就会慢慢泄漏出来; 它只会限制你填写桶.

此代码段将$minute_throttle在每个请求上计算新值.我指定了分钟,$minute_throttle因为你可以在任何时间段添加限制,例如每小时,每天等等......虽然不止一个会很快开始让用户感到困惑.

$minute = 60;
$minute_limit = 100; # users are limited to 100 requests/minute
$last_api_request = $this->get_last_api_request(); # get from the DB; in epoch seconds
$last_api_diff = time() - $last_api_request; # in seconds
$minute_throttle = $this->get_throttle_minute(); # get from the DB
if ( is_null( $minute_limit ) ) {
    $new_minute_throttle = 0;
} else {
    $new_minute_throttle = $minute_throttle - $last_api_diff;
    $new_minute_throttle = $new_minute_throttle < 0 ? 0 : $new_minute_throttle;
    $new_minute_throttle += $minute / $minute_limit;
    $minute_hits_remaining = floor( ( $minute - $new_minute_throttle ) * $minute_limit / $minute  );
    # can output this value with the request if desired:
    $minute_hits_remaining = $minute_hits_remaining >= 0 ? $minute_hits_remaining : 0;
}

if ( $new_minute_throttle > $minute ) {
    $wait = ceil( $new_minute_throttle - $minute );
    usleep( 250000 );
    throw new My_Exception ( 'The one-minute API limit of ' . $minute_limit 
        . ' requests has been exceeded. Please wait ' . $wait . ' seconds before attempting again.' );
}
# Save the values back to the database.
$this->save_last_api_request( time() );
$this->save_throttle_minute( $new_minute_throttle );



2> Markus Malku..:

您可以使用令牌桶算法控制速率,该算法与漏桶算法相当.请注意,您必须在进程(或您想要控制的任何范围)上共享存储桶的状态(即令牌数量).因此,您可能需要考虑锁定以避免竞争条件.

好消息:我为你做了所有这些:bandwidth-throttle/token-bucket

use bandwidthThrottle\tokenBucket\Rate;
use bandwidthThrottle\tokenBucket\TokenBucket;
use bandwidthThrottle\tokenBucket\storage\FileStorage;

$storage = new FileStorage(__DIR__ . "/api.bucket");
$rate    = new Rate(10, Rate::SECOND);
$bucket  = new TokenBucket(10, $rate, $storage);
$bucket->bootstrap(10);

if (!$bucket->consume(1, $seconds)) {
    http_response_code(429);
    header(sprintf("Retry-After: %d", floor($seconds)));
    exit();
}

推荐阅读
mobiledu2402852413
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有