Guava限流

Guava限流

为什么要做限流

通常我们的应用在部署之前都会先进行评估,有多少的调用量,需要多少台机器,能承受多大的流量;但是难免会有流量突然增大的时候,比如某时段某个接口突然遭受攻击,这时候某些机器可能会承受不了这个压力,导致崩溃,从而导致整个系统不可用。在我们的系统中, 会设置一定的阈值,保护我们的系统能正常运行。

通常我们流量控制的策略有:限流、降级、分流

原理

常用的限流算法有两种:令牌桶算法和漏桶算法。

漏桶算法

有一个漏桶,按照固定的出水速率漏水,进水的速率是不确定的,如果桶中的水满了,就会溢出(拒绝请求)。因为桶的容量(能承受的最大流量)是固定的,所以如果进水的速率大于出水的速率,一定时间后,就会导致直接溢出。

漏桶算法示意图

漏桶有两个变量,一个是水桶的大小,另一个是漏洞的大小。

缺点:因为漏桶出水的速率是固定的,所以无论流量是大还是小,出水速率都是不变的,这就缺乏效率了。

令牌桶算法

相比于漏桶算法,令牌桶算法在流量突然激增时,处理请求效率高得多。

有一个令牌桶,每次按照固定速率往里面加令牌,来一个请求,则从令牌桶中拿一个令牌,如果令牌桶中没有令牌,则拒绝请求。

当桶满的时候,新加的令牌就会被丢弃。

4fed1343611680243afeed16387ee10434f.jpg

如果流量增大的话,我们可以控制添加令牌的速率,这样的话处理请求的效率就上去了,这就是相比漏桶算法更好的地方。

实战

例子主要是通过guava的rateLimiter来做限流:

增加一个注解:

@Inherited
@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimitAnnotation {
}

对该注解增加一个切面:

@Aspect
@Component
public class RateLimitAop {
  	//限流每秒1次。如果设置为n,则每秒限流为1/n
    private RateLimiter rateLimiter= RateLimiter.create(1);

    @Pointcut(value = "@annotation(cn.tongdun.fp.admin.annotation.RateLimitAnnotation)")
    public void rateLimit(){

    }

    @Around("rateLimit()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Boolean flag = rateLimiter.tryAcquire();
        Object obj = null;
        try {
            if (flag) {
                obj = joinPoint.proceed();
            }else{
                throw new Exception("限流");
            }
        } catch (Throwable e) {
            throw e;
        }
        return obj;
    }
}

使用了该注解的接口,会被拦截:

@RateLimitAnnotation
public void test(Student student) {
  ...
}
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值