Base-admin笔记

发布时间 2023-09-15 08:27:34作者: 酒宴花窗

令牌桶

令牌桶限流,在SpringCloud分布式下限流,需要把令牌桶放到一个公共的地方,如Zuul路由,guava里有现成的基于令牌桶的限流实现。

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。 当桶满时,新添加的令牌被丢弃或拒绝。

令牌桶算法是一个存放固定容量令牌(token)的桶,按照固定速率往桶里添加令牌。令牌桶算法基本可以用下面的几个概念来描述:

令牌将按照固定的速率被放入令牌桶中。比如每秒放10个。
桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。
当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。
如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。

令牌桶
令牌算法是根据放令牌的速率去控制输出的速率,也就是上图的to network的速率。to network我们可以理解为消息的处理程序,执行某段业务或者调用某个RPC。

​通俗的理解,令牌桶是一个水桶,而令牌是通过一根水管流到水桶中的水

​令牌桶的填满时间,是由桶的自身容量、令牌漏出速率(桶下面的水管)、超过平均速率的突发流量持续的时间三个方面共同决定的。如果突发流量的时间比较短,令牌桶不会溢出,在通信流上不会受到影响,如果突发流量比较大,时间比较长,那令牌桶就会溢出,多余的通信流就会被限制。

​#### 令牌桶算法和漏桶算法的区别

  主要区别在于“漏桶算法”能够强行限制数据的传输速率,而“令牌桶算法”在能够限制数据的平均传输速率外,还允许某种程度的突发传输。在“令牌桶算法”中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,因此它适合于具有突发特性的流量。

@Slf4j
@Dependson("asyncTaskExecutor")
@Component
public class RateLimiter{
    private Integer limit=10;
    private Integer speed=3;
    private static volatile Integer tokens=0;
    public RateLimiter(){
        RateLimiter.tokens=this.limit;
    }
    @Async("asyncTaskExecutor")
    public void asyncTask(){
        log.info("RateLimiter Starting...");
        while(true){
            try{
                Thread.sleep(1000L);
                int newTokens=tokens+speed;
                if(newTokens>limit){
                    tokens=limit;
                }else{
                    tokens=newTokens;
                }
            }catch(Exception e){
                log.error(ErrorUtil.errorInfoToString(e));
            }
        }
    }
    public synchronized boolean execute(){
        if(tokens>0){
            tokens=tokens-1;
            return true;
        }
        return false;
    }
}