Guava限流设计上 | 8月更文挑战

207 阅读2分钟

这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战

前言

Guava 是Google开源的工具库,提供了一些常用的便利的操作工具类,好好利用可减少空指针、异步操作等引发的问题,涵盖许多类:Splitter 分割器、CharMatcher、Ints、Multiset Code。谁用谁知道。 本次主要分上下文介绍Guava中的限流设计,漏桶算法和令牌算法。

一、限流这个词对程序员来说肯定不陌生,为什么需要做限流?

事实上每个API接口都会有一定的访问数量限制,当超过这个访问上限或者并发量超出承受范围时,服务器可能承受不住,导致系统瘫坏。这时候需要考虑限制请求流量保证接口的可用性或者降级可用性。可以理解就是给接口加个保险丝,当请求超出预期数,系统压力过大时保险丝就会起作用自动切断。

通常的策略就是拒绝多余的访问,或者让多余的访问排队等待服务,或者引流。

二、限流算法

常用限流算法有漏桶算法和令牌算法。

漏桶算法

漏桶(Leaky Bucket)算法其实原理很简单,核心就是水流速度,水(相当于“请求”)先进入到漏桶里,漏桶以一定的速度出水(接口的响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法会强行限制数据的传输速率。

1.png

缺点

因为漏桶的漏出速率是固定的参数,所以,即使系统请求没有达到限制速率或远远小于限制速率,漏桶算法也不能使流速突发(burst)到端口速率,一定程度上使得系统缺乏效率。

public class Limiterstest {
 
private static Double RATE = 11d;//每秒漏水速率
private static Double BURST = 200d;//桶大小
 
//更新水量
private Double refreshWater(Double water,Long refreshTime){
Long now = System.currentTimeMillis();
 
if(water == 0d){
return water;
}
BigDecimal bigResult = BigDecimal.valueOf(now - refreshTime).divide(BigDecimal.valueOf(1000));
System.out.println("当前漏水:" + bigResult.intValue() * RATE);
water = Math.max(0,water - bigResult.intValue() * RATE);
return water;
}
 
/**
* 漏桶伪算法
*/
@Test
public void testLeakyBucket(){
 
int count = 0;
 
Long refreshTime = System.currentTimeMillis();//上一次更新时间点offeset概念
 
Double water = 20d;//最新水量(动态)
 
while (count < 500){
 
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
water = refreshWater(water,refreshTime);
refreshTime = System.currentTimeMillis();
//水没满,继续加水
if(water < BURST){
System.out.println("水没满,当前水位:" + water);
}else {
System.out.println("水满了!!!!,当前水位:" + water);
}
water= water + 20;
count ++;
      }
 
    }
 
}