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限流的目的。架構

相關文章
相關標籤/搜索