速率限制真实世界的用户是残酷的、不耐烦的,并且充满不确定性。在高并发系统中,可能会出现服务器被虚假请求轰炸的情况,因此您可能希望对此进行控制。一些实际用例可能如下所示:API配额管理-作为提供商,您可能希望根据用户的付款状态限制对服务器的API请求速率。这可以在客户端或服务器端完成。安全-防止DDOS攻击。成本控制——这对于服务端甚至客户端都不是必需的。如果一个组件以非常高的速率发出事件,它可能有助于控制它,它可能有助于控制从客户端发送的遥测数据。速率限制处理时的选项根据我们处理的请求/事件的类型,可能会发生以下情况:我们可能会丢弃额外的请求我们可能会选择让请求等待,直到系统将它们降低到预定义的速率。常见的速率限制算法令牌桶算法漏桶算法我们不会深入探讨这些算法的内部细节,因为它超出了本文的范围。我们将重点关注令牌桶算法。其要求如下。令牌桶算法是基于固定容量的桶以固定速率添加令牌的类比。在API被允许继续之前,将检查存储桶以查看它当时是否包含至少一个令牌。如果令牌存在,则进行API调用。如果不是,丢弃消息/或让它等待。需求应该能够接受每秒或速率所需的(TPS)交易。如果超过我们定义的比率,则应放弃交易。应该在两者的情况下工作。高级功能(在后续文章中实现)应该可以消除突发的请求。比如我们定义TPS为5,5个请求同时到达,那么它应该可以定时排队,即每200ms执行一次请求。它需要一个内部定时电路。如果我们的TPS为5,并且在其中一个1秒时段内我们在下一秒仅花费3个代币,那么我们应该能够提供5+2=7个代币作为奖励。但速率是每个令牌的1/7(142.28毫秒)。奖金不应结转到下一个插槽。让我们首先定义我们的速率限制器:/**速率限制器有助于限制一段代码的执行速率。该速率根据TPS(每秒事务数)定义。速率5表示每秒5个事务。事务可以是数据库调用、API调用或简单的函数调用。
每个{@linkRateLimiter}实现都应该实现{@linkRateLimiter#throttle(Code)}或{@linkRateLimiter#enter()}.他们也可以选择全部实现。
{@link代码}代表一段需要限速的代码。它可能是一个函数调用,如果要限制速率的代码跨越多个函数,我们需要使用entry()和exit()契约。*/publicinterfaceRateLimiter{/***速率限制作为参数传递到内部的代码。**@param代码表示需要速率限制的代码段。*@return如果执行则为真,否则为假。*/booleanthrottle(Codecode);/***当需要r的那段代码atelimited不能表示为连续的*代码,那么在我们开始执行代码之前应该使用entry()。这将代码置于速率*限制边界内。**@returntrue如果代码将执行,如果速率受限则返回false。*