当前位置: 首页 > 知识库问答 >
问题:

如果API速率限制超过使用WebApiThrottle-C#Web API的限制,则阻止API请求5分钟

劳仲渊
2023-03-14

在WebAPI中有一个非常好的用于限制API速率的库WebAPI
如Wiki页面所述,我可以根据API调用的授权令牌头对API进行评级限制
但是,如果此api速率限制超过,我如何在接下来的5分钟内阻止api调用?此外,在未来5分钟内的任何请求都不会重置速率限制超出时间。

我检查了代码,但找不到这个功能。如果有人能建议,还有其他方法吗?

共有1个答案

况庆
2023-03-14

目前,我正在使用WebApitrottle的这个分支,并将dll手动添加到解决方案中@adamriyadi已经在fork中实现了这个特性。等着它来拿包裹。

更新:后来,我使用HttpRuntime实现了自己的API速率限制和阻塞周期。缓存。因此,不需要添加任何额外的库。

public class ThrottleAttribute : ActionFilterAttribute
    {
        private int _API_RATEQUOTA = 60;

        // per x minute value
        private int _API_TIMELIMIT = 1;

        private int _API_BLOCKDURATION = 5;

        private readonly object syncLock = new object();

        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            // Extract access_token or id or ip address to uniquely identify an API call
            var access_token = AuthHelper.GetAuthToken(actionContext.Request);

            if (access_token != null)
            {

                string throttleBaseKey = GetThrottleBaseKey(access_token);
                string throttleCounterKey = GetThrottleCounterKey(access_token);

                lock (syncLock)
                {
                    //add a listner for new api request count
                    if (HttpRuntime.Cache[throttleBaseKey] == null)
                    {
                        // add api unique key.. this cache will get expire after _API_TIMELIMIT
                        HttpRuntime.Cache.Add(throttleBaseKey,
                            DateTime.UtcNow,
                            null,
                            DateTime.Now.AddMinutes(_API_TIMELIMIT),
                            Cache.NoSlidingExpiration,
                            CacheItemPriority.High,
                            null);

                        // add count as value for that api.. this cache will get expire after _API_TIMELIMIT
                        HttpRuntime.Cache.Add(throttleCounterKey,
                           1,
                           null,
                           DateTime.Now.AddMinutes(_API_TIMELIMIT),
                           Cache.NoSlidingExpiration,
                           CacheItemPriority.High,
                           null);
                    }
                    else
                    {
                        //listener exists for api request count
                        var current_requests = (int)HttpRuntime.Cache[throttleCounterKey];

                        if (current_requests < _API_RATEQUOTA)
                        {
                            // increase api count
                           HttpRuntime.Cache.Insert(throttleCounterKey,
                           current_requests + 1,
                           null,
                           DateTime.Now.AddMinutes(_API_TIMELIMIT),
                           Cache.NoSlidingExpiration,
                           CacheItemPriority.High,
                           null);
                        }

                        //hit rate limit, wait for another 5 minutes (_API_BLOCKDURATION)
                        else
                        {
                            HttpRuntime.Cache.Insert(throttleBaseKey,
                           DateTime.UtcNow,
                           null,
                           DateTime.Now.AddMinutes(_API_BLOCKDURATION),
                           Cache.NoSlidingExpiration,
                           CacheItemPriority.High,
                           null);

                            HttpRuntime.Cache.Insert(throttleCounterKey,
                          current_requests + 1,
                          null,
                          DateTime.Now.AddMinutes(_API_BLOCKDURATION),
                          Cache.NoSlidingExpiration,
                          CacheItemPriority.High,
                          null);

                            Forbidden(actionContext);
                        }
                    }
                }
            }
            else
            {
                BadRequest(actionContext);
            }

            base.OnActionExecuting(actionContext);
        }

        private string GetThrottleBaseKey(string app_id)
        {
            return Identifier.THROTTLE_BASE_IDENTIFIER + app_id;
        }

        private string GetThrottleCounterKey(string app_id)
        {
            return Identifier.THROTTLE_COUNTER_IDENTIFIER + app_id;
        }

        private void BadRequest(HttpActionContext actionContext)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest);
        }

        private void Forbidden(HttpActionContext actionContext)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden, "Application Rate Limit Exceeded");
        }

    }

    public static class Identifier
    {
        public static readonly string THROTTLE_BASE_IDENTIFIER = "LA_THROTTLE_BASE_";
        public static readonly string THROTTLE_COUNTER_IDENTIFIER = "LA_THROTTLE_COUNT_";
    }

现在用[ThrottleAtoun]装饰所需的API

 类似资料:
  • 在我的jenkins工作中,我得到这个错误为我的bot用户。我的限制是5000,我看到每秒钟大约有100个请求,我不确定哪个工作/服务正在使用机器人的请求。理想情况下,我的其他jenkins工作应该每分钟最多占用1个请求。 有没有办法找出是什么导致了如此高的请求率?或者任何API调用来列出在最后一分钟内进行的所有API调用或类似的东西?

  • 假设我正在创建一个PWA(渐进式网络应用程序),用户可以在其中添加产品。这些产品的价格从0.01 EUR到1.00 EUR不等。我使用条纹支付。条纹订单对象不支持动态价格,动态传递,没有任何引用(一种外键)。要接受订单,Stripe需要引用SKU。在我的例子中,这个SKU将是产品价格的变化。这意味着,为了涵盖所有变化,我需要100个SKU,从1(0.01欧元)到100(1,00欧元)。因此,对于在

  • 我正在使用ProjectReactor使用rest从web服务加载数据。这是与多个线程并行完成的。我开始达到web服务的速率限制,因此我希望每秒最多发送10个请求,以避免出现这些错误。用Reactor我该怎么做? 使用zipWith(Mono.delayMillis(100))?还是有更好的办法? 非常感谢。

  • 问题内容: 我正在用GRequests和lxml在Python 2.7.3中编写一个小脚本,这将允许我从各个网站收集一些可收集的卡价格并进行比较。问题是网站之一限制了请求的数量,如果我超过了它,则会发回HTTP错误429。 有没有一种方法可以限制GRequestes中的请求数量,以使我不超过我指定的每秒请求数量?另外-如果发生HTTP 429,如何让GRequestes在一段时间后重试? 附带说明

  • 我正在用Python 2.7.3编写一个小脚本,其中包含GRequests和lxml,它将允许我从各种网站收集一些可收集的卡价格并进行比较。问题是其中一个网站限制了请求的数量,如果我超过它,就会发回HTTP错误429。 有没有办法在grequests中增加限制请求数,这样我就不会超过我指定的每秒请求数?还有——如果HTTP 429出现,我如何让GRequestes在一段时间后重试? 另一方面,他们

  • 我正在googledriveapi之上构建一个web应用程序。基本上,web应用程序显示照片和视频。媒体存储在Google Drive文件夹中:一旦通过身份验证,应用程序将向Google Drive API发出请求,以获取媒体的URL,并显示每个URL。目前,我只有16幅图像要显示。这些图像是在应用程序中硬写的(用于演示)。 我的应用程序访问Google Drive API时遇到问题。事实上,在多