简介
Rate Limiter 是 Resilience4j 提供的一个重要组件,用于限制对资源(如API接口)的访问速率,以确保系统的高可用性和可靠性。Rate Limiter 通过控制单位时间内允许通过的请求数量来防止系统过载。本文将详细介绍如何在Java中使用Resilience4j的Rate Limiter。
内部机制
Resilience4j的Rate Limiter将自纪元开始以来的所有纳秒分成周期,每个周期的持续时间由RateLimiterConfig.limitRefreshPeriod
配置。在每个周期开始时,Rate Limiter会设置该周期内允许的活跃权限数(RateLimiterConfig.limitForPeriod
)。
Resilience4j提供了两种Rate Limiter实现:
- AtomicRateLimiter:通过
AtomicReference
管理状态,其内部状态(State
)是完全不可变的,包含activePermissions
(最后一次调用后剩余的可用权限数,如果某些权限被预留,则可能为负数)。 - SemaphoreBasedRateLimiter:使用Semaphores和调度器,在每个
limitRefreshPeriod
后刷新权限。
创建和配置RateLimiter
创建RateLimiterRegistry
类似于CircuitBreaker模块,RateLimiter模块也提供了一个内存中的RateLimiterRegistry
,用于管理(创建和检索)RateLimiter实例。
java
代码解读
复制代码
RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.ofDefaults();
自定义全局RateLimiterConfig
你可以通过RateLimiterConfig
构建器来创建自定义的全局配置。
java
代码解读
复制代码
RateLimiterConfig config = RateLimiterConfig.custom() .limitRefreshPeriod(Duration.ofMillis(1)) // 刷新周期 .limitForPeriod(10) // 每周期允许的最大请求数 .timeoutDuration(Duration.ofMillis(25)) // 请求超时时间 .build(); // 使用自定义配置创建Registry RateLimiterRegistry registryWithCustomConfig = RateLimiterRegistry.of(config);
创建RateLimiter实例
通过Registry可以创建和检索RateLimiter实例。
这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】免费获取
java
代码解读
复制代码
RateLimiter rateLimiterWithDefaultConfig = registryWithCustomConfig.rateLimiter("name1"); // 使用默认配置 RateLimiter rateLimiterWithCustomConfig = registryWithCustomConfig.rateLimiter("name2", config); // 使用自定义配置
使用RateLimiter
装饰并执行功能接口
你可以使用RateLimiter来装饰任何可调用的方法或操作,限制其调用频率。
java
代码解读
复制代码
// 假设有一个BackendService类,其中有一个doSomething方法 BackendService backendService = new BackendService(); // 使用RateLimiter装饰doSomething方法 CheckedRunnable restrictedCall = RateLimiter.decorateCheckedRunnable(rateLimiterWithCustomConfig, backendService::doSomething); // 执行操作,并处理异常情况 Try.run(restrictedCall) .andThenTry(restrictedCall) .onFailure(RequestNotPermitted.class, throwable -> LOG.info("Wait before calling it again :)"));
修改RateLimiter参数
在运行时,你可以修改RateLimiter的某些参数,如超时时间和每周期的请求限制数。
java
代码解读
复制代码
rateLimiterWithCustomConfig.changeTimeoutDuration(Duration.ofMillis(50)); // 修改超时时间 rateLimiterWithCustomConfig.changeLimitForPeriod(20); // 修改每周期的限制数
请注意,新的超时时间不会影响当前正在等待权限的线程,新的每周期限制数将从下一个周期开始应用。
监听事件
RegistryEvents
你可以注册事件监听器来响应RateLimiterRegistry中的事件(如RateLimiter的添加、替换或删除)。
java
代码解读
复制代码
registryWithCustomConfig.getEventPublisher() .onEntryAdded(entryAddedEvent -> LOG.info("RateLimiter {} added", entryAddedEvent.getAddedEntry().getName())) .onEntryRemoved(entryRemovedEvent -> LOG.info("RateLimiter {} removed", entryRemovedEvent.getRemovedEntry().getName()));
RateLimiterEvents
RateLimiter会发出包含成功获取权限或获取失败信息的事件流。你可以注册为事件消费者来消费这些事件。
java
代码解读
复制代码
// 使用RxJava或其他响应式编程库来转换EventPublisher为Reactive Stream
Spring 项目集成 ratelimiter 实战
注册
java
代码解读
复制代码
@SpringBootApplication public class demoApplication { // 其他代码... @Bean("secondLismiter") public RateLimiter perSecondLimiter() { return RateLimiterRegistry.ofDefaults().rateLimiter("second-limiter", RateLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(5)) .limitForPeriod(15) // 每秒 15 次 .limitRefreshPeriod(Duration.ofSeconds(1)) .build()); } @Bean("minuteLimiter") public RateLimiter perMinuteLimiter() { return RateLimiterRegistry.ofDefaults().rateLimiter("minute-limiter", RateLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(5)) .limitForPeriod(5000) // 每分 5000 次数 .limitRefreshPeriod(Duration.ofMinutes(1)) .build()); } // 其他代码... }
使用
java
代码解读
复制代码
@Resource(name = "SecondLimiter") private RateLimiter secondLimiter; @Resource(name = "minuteLimiter") private RateLimiter minuteLimiter; public DemoController() { @RequestMapping("/demo/test") @ResponseBody public void test() { // 其他代码... // 分、秒限流器剩余可用次数 LOG.info("分限流器可用次数:" + secondLimiter.getMetrics().getAvailablePermissions()); LOG.info("秒限流器可用次数:" + minuteLimiter.getMetrics().getAvailablePermissions()); // 限流器校验请求 if (secondLimiter.acquirePermission() && minuteLimiter.acquirePermission(toList.length)) { // 执行通过请求 // DEMO } else { // 打印限流请求 // LOG.warn("") } // 其他代码... } }
总结
Resilience4j的RateLimiter是一个功能强大的工具,用于限制对系统资源的访问速率,从而保护系统免受过载和拒绝服务攻击。通过自定义配置和灵活的API,你可以轻松地将其集成到你的Java应用程序中,并确保服务的高可用性和可靠性。