TPS限流

限流是高可用服务须要具有的能力之一 ,粗暴简单的就像咱们以前作的并发数控制。好一点的有tps限流,可用令牌桶等算法实现。《亿级流量网站架构核心技术》一书P67限流详解也有讲。dubbo提供了此机制,TpsLimitFilter。guava也提供了相应的工具类RateLimiter。java

1. dubbo提供的tps限流

1.1 demo使用

1.1.1 在source folder下放置,META-INF/dubbo/com.alibaba.dubbo.rpc.Filter

里面写入 tpslimiter=com.alibaba.dubbo.rpc.filter.TpsLimitFilter
表示将TpsLimitFilter这个filter的扩展给装配给dubbogit

1.1.2 provider侧的配置

<dubbo:service interface="org.simonme.dubbo.demo.provider.service.HelloService" ref="m00001.app001.xx.helloService" filter="tpslimiter">
    <dubbo:parameter key="tps" value="5" />
</dubbo:service>

意思对HelloService 这个接口在provider侧作tps为5的限流,默认间隔是60s,能够经过tps.interval这个parameter进行配置,单位是毫秒。注意此处配置的tps为5,不是每秒限制经过5个之内的请求,而是单位时间间隔内经过5个之内的请求。关于单位时间间隔前面解释了。github

1.2 若是超限了是什么现象?

客户端会抛出rpc调用异常:
com.alibaba.dubbo.rpc.RpcException: Failed to invoke service org.simonme.dubbo.demo.provider.service.HelloService.sayHello because exceed max service tps算法

1.3 原理分析

主要是DefaultTPSLimiterStatItem两个类配合完成。采用的是令牌桶算法,实如今StatItem类中。
大意是:
每隔一个单位时间后重置令牌桶中令牌的数量,而后每次请求来的时候减1,减到小于0时,拒绝请求。spring

long now = System.currentTimeMillis();
if (now > lastResetTime + interval) {
    token.set(rate);
    lastResetTime = now;
}

int value = token.get();
boolean flag = false;
while (value > 0 && !flag) {
    flag = token.compareAndSet(value, value - 1);
    value = token.get();
}

注意:此实现依赖系统时间,若是想用相对时间实现,能够参见这里 dubbo的TPS限流模块在运行时系统时间发生变化的状况下限流不能正常工做 #2345apache

2. spring cloud

对于采用spring cloud的架构的项目,能够借助guava的RateLimiter来实现ZuulFilter的子类来达成tps限流的目的。架构

相关文章
相关标签/搜索