如何限制我网站的 API 用户? [英] How do I throttle my site's API users?

查看:24
本文介绍了如何限制我网站的 API 用户?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我网站的合法用户偶尔会用 API 请求攻击服务器,从而导致不良结果.我想设置一个限制,不超过每 5 秒一次 API 调用或每分钟 n 次调用(还没有弄清楚确切的限制).我显然可以将每个 API 调用记录到数据库中,并对每个请求进行计算以查看它们是否超过限制,但是每个请求的所有这些额外开销都将违背目的.我可以使用哪些其他资源密集度较低的方法来制定限制?我正在使用 PHP/Apache/Linux,这是值得的.

The legitimate users of my site occasionally hammer the server with API requests that cause undesirable results. I want to institute a limit of no more than say one API call every 5 seconds or n calls per minute (haven't figured out the exact limit yet). I could obviously log every API call in a DB and do the calculation on every request to see if they're over the limit, but all this extra overhead on EVERY request would be defeating the purpose. What are other less resource-intensive methods I could use to institute a limit? I'm using PHP/Apache/Linux, for what it's worth.

推荐答案

好吧,如果没有任何写入服务器,就无法完成我所要求的操作,但我至少可以消除每次记录要求.一种方法是使用漏桶"节流方法,它只跟踪最后一个请求($last_api_request)和时间范围内请求数/限制的比率($minute_throttle).漏桶永远不会重置它的计数器(不像 Twitter API 的节流阀每小时重置一次),但是如果桶变满(用户达到限制),他们必须等待 n 秒让桶清空在他们可以提出另一个请求之前.换句话说,它就像一个滚动限制:如果在时间范围内有先前的请求,它们就会慢慢地从桶中泄漏出来;它只会在你填满桶时限制你.

Ok, there's no way to do what I asked without any writes to the server, but I can at least eliminate logging every single request. One way is by using the "leaky bucket" throttling method, where it only keeps track of the last request ($last_api_request) and a ratio of the number of requests/limit for the time frame ($minute_throttle). The leaky bucket never resets its counter (unlike the Twitter API's throttle which resets every hour), but if the bucket becomes full (user reached the limit), they must wait n seconds for the bucket to empty a little before they can make another request. In other words it's like a rolling limit: if there are previous requests within the time frame, they are slowly leaking out of the bucket; it only restricts you if you fill the bucket.

此代码段将针对每个请求计算一个新的 $minute_throttle 值.我在 $minute_throttle 中指定了 minute 因为您可以为任何时间段添加节流阀,例如每小时、每天等......它让用户感到困惑.

This code snippet will calculate a new $minute_throttle value on every request. I specified the minute in $minute_throttle because you can add throttles for any time period, such as hourly, daily, etc... although more than one will quickly start to make it confusing for the users.

$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 );

这篇关于如何限制我网站的 API 用户?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆