限流是高可用服務須要具有的能力之一 ,粗暴簡單的就像咱們以前作的併發數控制。好一點的有tps限流,可用令牌桶等算法實現。《億級流量網站架構核心技術》一書P67限流詳解也有講。dubbo提供了此機制,TpsLimitFilter。guava也提供了相應的工具類RateLimiter。java
裏面寫入 tpslimiter=com.alibaba.dubbo.rpc.filter.TpsLimitFilter
表示將TpsLimitFilter這個filter的擴展給裝配給dubbogit
<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
客戶端會拋出rpc調用異常:
com.alibaba.dubbo.rpc.RpcException: Failed to invoke service org.simonme.dubbo.demo.provider.service.HelloService.sayHello because exceed max service tps算法
主要是DefaultTPSLimiter
和StatItem
兩個類配合完成。採用的是令牌桶
算法,實如今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限流模塊在運行時系統時間發生變化的狀況下限流不能正常工做 #2345。apache
對於採用spring cloud的架構的項目,能夠藉助guava的RateLimiter
來實現ZuulFilter
的子類來達成tps限流的目的。架構