项目简介
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方法访问一次消耗的令牌数1timeUnit时间单位TimeUnit.SECONDSinterval时间间隔60count可调用次数1000enable是否启用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 默认基于 IPmethodService方法标识策略RateLimitMethodService 默认基于方法名+参数类型rejectListener拒绝策略RateLimitRejectListenerException 限流时抛出异常其中 rateLimit 内置 RateLimits 工具中的策略如下:
方法说明
fixedWindow()固定窗口slideWindow(int windowNum)滑动窗口,可指定窗口大小slideWindow()滑动窗口,默认为 10slideWindowQueue()滑动窗口,基于队列的实现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 注解即可。
@Servicepublic 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")@EnableRateLimitpublic class SpringConfig {}
@EnableRateLimit 的属性配置和 RateLimitBs 属性是以一一对应的。
方法说明默认值
rateLimit限流策略令牌桶算法timer时间策略系统时间cacheService缓存策略基于本地 map 的缓存策略cacheKeyNamespace缓存KEY命名空间RATE-LIMIT 避免不同的应用,命名冲突。configService限制配置策略默认基于方法上的注解tokenService身份标识策略默认基于 IPmethodService方法标识策略默认基于方法名+参数类型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 保持一致。
缓存相关工具
cache: 手写渐进式 redis
common-cache: 通用缓存标准定义
redis-config: 兼容各种常见的 redis 配置模式
lock: 开箱即用的分布式锁
resubmit: 防重复提交
rate-limit: 限流
只剩下一条路,那就是成功的路。