熔断限流
限流
根据排队理论,具有延迟的服务随着请求量的不断提升,其平均响应时间也会迅速提升,为了保证服务的SLA(Service-Level Agreement 服务等级协议),有必要控制单位时间的请求量。这就是限流为什么愈发重要的原因。
分类
qps限流
限制每秒处理请求数不超过阈值
并发限流
限制同时处理的请求数目。Java 中的 Semaphore(信号量) 是做并发限制的好工具,特别适用于资源有效的场景。
单机限流
Guava 中的 RateLimiter(内部采用令牌捅算法实现)。
集群限流
redis限流,计时器和计数器处理、key加秒为key
nginx(+lua)前端限流,按照一定的规则如帐号、IP、系统调用逻辑等在Nginx层面做限流
算法
常见的限流算法有:令牌桶、漏桶。计数器也可以进行粗暴限流实现。
漏桶算法

令牌桶算法

实施方案
RPC限流(dubbo)
dubbo调用模型
连接调用图

调用时关键参数影响

分析
1:当consumer发起一个请求时,首先经过active limit(参数actives)进行方法级别的限制,其实现方式为CHM中存放计数器(AtomicInteger),请求时加1,请求完成(包括常)减1,如果超过actives则等待有其他请求完成后重试或者超时后失败;
2:从多个连接(connections)中选择一个连接发送数据,对于默认的netty实现来说,由于可以复用连接,默认一个连接就可以。不过如果你在压测,且只有一个consumer,一个provider,此时适当的加大connections确实能够增强网络传输能力。但线上业务由于有多个consumer多个provider,因此不建议增加connections参数;
3:连接到达provider时(如dubbo的初次连接),首先会判断总连接数是否超限(acceps),超过限制连接将被拒绝;
4:连接成功后,具体的请求交给io thread处理。io threads虽然是处理数据的读写,但io部分为异步,更多的消耗的是cpu,因此iothreads默认cpu个数+1是比较合理的设置,不建议调整此参数;
5:数据读取并反序列化以后,交给业务线程池处理,默认情况下线程池为fixed,且排队队列为0(queues),这种情况下,最大并发等于业务线程池大小(threads),如果希望有请求的堆积能力,可以调整queues参数。如果希望快速失败由其他节点处理(官方推荐方式),则不修改queues,只调整threads;
6:execute limit(参数executes)是方法级别的并发限制,原理与actives类似,只是少了等待的过程,即受限后立即失败;
7:tps,控制指定时间内(默认60s)的请求数。注意目前dubbo默认没有支持该参数
从上面的分析,可以看出如果 (consumer数 * actives > provider数 * threads) 且 (queues=0),则会存在部分请求无法申请到资源,重试也有很大几率失败。
当需要对一个接口的不同方法进行不同的并发控制时使用executes,否则调整threads就可以。
内容引用自 dubbo参数调优说明
dubbo filter
dubbo提供了多个和请求相关的filter 我们可以看到:ActiveLimitFilter ExecuteLimitFilter TPSLimiterFilter
ActiveLimitFilter
@Activate(group = Constants.CONSUMER, value = Constants.ACTIVES_KEY)
作用于客户端,控制客户端同样的方法可同时运行的次数【即该方法的并发度】
dubbo:reference 配置类:org.apache.dubbo.config.ReferenceConfig actives:(int default 0) 每服务消费者每服务每方法最大并发调用数 2.0.5以上版本 dubbo:consumer 配置类: org.apache.dubbo.config.ConsumerConfig 同时为 dubbo:reference 缺省值设置 default.actives:(int default 0)
原创不易,完成人机校验,阅读全文