項目簡介
rate-limit 是一個爲 java 設計的漸進式限流工具。
目的是爲了深入學習和使用限流,後續將會持續迭代。
特性
漸進式實現
支持獨立於 spring 使用
支持整合 spring
支持整合 spring-boot
內置多種限流策略
快速開始
需求
jdk 1.7
maven 3.x+
maven 導入
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>rate-limit-core</artifactId>
<version>1.1.0</version>
</dependency>
入門例子
方法定義
@RateLimit
限流注解放在方法上,指定對應的限制頻率。
也可以定義在類上,默認下面的所有方法生效。方法上的優先級高於類。
屬性 | 說明 | 默認值 |
---|---|---|
value | 方法訪問一次消耗的令牌數 | 1 |
timeUnit | 時間單位 | TimeUnit.SECONDS |
interval | 時間間隔 | 60 |
count | 可調用次數 | 1000 |
enable | 是否啓用 | true |
默認爲 60S 內,可以調用 1000 次。
public class UserService {
@RateLimit(interval = 2, count = 5)
public void limitCount() {
log.info("{}", Thread.currentThread().getName());
}
}
這個例子中我們 2S 內最多調用 5 次。
代碼測試
RateLimitProxy.getProxy(xxx)
通過字節碼獲取方法對應的方法代理。
@Test(expected = RateLimitRuntimeException.class)
public void limitCountErrorTest() {
UserService userService = RateLimitProxy.getProxy(new UserService());
for(int i = 0; i < 3; i++) {
userService.limitCount();
}
}
當調用超出限制時,默認拋出 RateLimitRuntimeException
異常。
這裏默認使用的是令牌桶算法,所以會出現異常。
重複註解 @RateLimits
有時候我們希望同時做多個的限制:
(1)一分鐘不超過 10 次
(2)一小時不超過 30 次
爲了支持多個配置,我們引入了新的註解 @RateLimits
,可以指定一個 @RateLimit
數組。
方法上同時使用 @RateLimits
+ @RateLimit
是可以同時生效的,不過爲了簡單,一般不建議混合使用。
@RateLimits({@RateLimit(interval = 2, count = 5)})
public void limitCount() {
//...
}
指定引導類
RateLimitProxy.getProxy(new UserService());
等價於
RateLimitProxy.getProxy(new UserService(), RateLimitBs.newInstance());
下面我們來一起看一下 RateLimitBs 引導類。
引導類
RateLimitBs
作爲引導類,便於用戶自定義配置。
方法 | 說明 | 默認值 |
---|---|---|
rateLimit | 限流策略 |
RateLimits.tokenBucket() 令牌桶算法 |
timer | 時間策略 |
Timers.system() 系統時間 |
cacheService | 緩存策略 |
CommonCacheServiceMap 基於本地 map 的緩存策略 |
cacheKeyNamespace | 緩存KEY命名空間 |
RATE-LIMIT 避免不同的應用,命名衝突。 |
configService | 限制配置策略 |
RateLimitConfigService 默認基於方法上的註解 |
tokenService | 身份標識策略 |
RateLimitTokenService 默認基於 IP |
methodService | 方法標識策略 |
RateLimitMethodService 默認基於方法名+參數類型 |
rejectListener | 拒絕策略 |
RateLimitRejectListenerException 限流時拋出異常 |
其中 rateLimit 內置 RateLimits
工具中的策略如下:
方法 | 說明 |
---|---|
fixedWindow() | 固定窗口 |
slideWindow(int windowNum) | 滑動窗口,可指定窗口大小 |
slideWindow() | 滑動窗口,默認爲 10 |
slideWindowQueue() | 滑動窗口,基於隊列的實現 |
leakyBucket() | 漏桶算法 |
tokenBucket() | 令牌桶算法 |
配置建議
分佈式系統,cacheService 建議使用基於 redis 的集中式緩存策略。
configService 如果想更加靈活,可以基於數據庫的配置查詢
RateLimitBs 引導類
RateLimitBs 默認配置如下:
RateLimitBs.newInstance()
.timer(Timers.system())
.methodService(new RateLimitMethodService())
.tokenService(new RateLimitTokenService())
.rejectListener(new RateLimitRejectListenerException())
.configService(new RateLimitConfigService())
.cacheService(new CommonCacheServiceMap())
.rateLimit(RateLimits.tokenBucket())
.cacheKeyNamespace(RateLimitConst.DEFAULT_CACHE_KEY_NAMESPACE);
spring 整合
maven 引入
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>rate-limit-spring</artifactId>
<version>1.1.0</version>
</dependency>
類定義
方法
和上面使用類似,直接在方法上聲明 @RateLimit
註解即可。
@Service
public class UserService {
private static final Log log = LogFactory.getLog(UserService.class);
@RateLimit(interval = 2, count = 5)
public void limitCount() {
log.info("{}", Thread.currentThread().getName());
}
}
配置
通過 @EnableRateLimit
聲明啓用限流。
@Configuration
@ComponentScan("com.github.houbb.rate.limit.test.core")
@EnableRateLimit
public class SpringConfig {
}
@EnableRateLimit
的屬性配置和 RateLimitBs 屬性是以一一對應的。
方法 | 說明 | 默認值 |
---|---|---|
rateLimit | 限流策略 | 令牌桶算法 |
timer | 時間策略 | 系統時間 |
cacheService | 緩存策略 | 基於本地 map 的緩存策略 |
cacheKeyNamespace | 緩存KEY命名空間 |
RATE-LIMIT 避免不同的應用,命名衝突。 |
configService | 限制配置策略 | 默認基於方法上的註解 |
tokenService | 身份標識策略 | 默認基於 IP |
methodService | 方法標識策略 | 默認基於方法名+參數類型 |
rejectListener | 拒絕策略 | 限流時拋出異常 |
這裏的屬性值,都是對應的 spring bean 名稱,支持用戶自定義。
spring-boot 整合
maven 引入
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>rate-limit-springboot-starter</artifactId>
<version>1.1.0</version>
</dependency>
使用
其他和 spring 保持一致。
後期 Road-MAP
@RateLimit
類級別 public 方法支持@RateLimit
多註解支持