概述
resilience4j-ratelimiter 可以用来控制指定时间内的请求数量,从而保证服务的可靠性。
比如,我们调用的第三方接口(如百度api,face++)通常会有流量的限制,此时,我们可以通过resilience4j控制流量。
当流量超过限制时,可以直接抛弃,也可以放入等待队列中。
RateLimiter的默认实现是AtomicRateLimiter
,通过AtomicReference
来管理状态, AtomicRateLimiter.State是不可修改的,它有如下属性:
- activeCycle: 上次调用占用的周期数,活跃周期数
- activePermissions:剩余的令牌数,当一个调用占用多个周期时,可能为负数。
- nanosToWait:获取令牌等待时间
另外也有一个通过信号量控制流量的实现SemaphoreBasedRateLimiter
。
参数说明
属性 | 默认值 | 说明 |
---|---|---|
timeoutDuration | 5[s] | 线程等待令牌的时间 |
limitRefreshPeriod | 500[ns] | 令牌刷新周期,每次刷新,剩余令牌数都恢复到默认值 |
limitForPeriod | 50 | 每个周期的初始令牌数 |
通过代码配置
//限制每秒10次调用
RateLimiterConfig config = RateLimiterConfig.custom()
.limitRefreshPeriod(Duration.ofSeconds(1))
.limitForPeriod(10)
.timeoutDuration(Duration.ofMillis(25))
.build();
// Create registry
RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.of(config);
// Use registry
RateLimiter rateLimiterWithDefaultConfig = rateLimiterRegistry
.rateLimiter("name1");
// Decorate your call to BackendService.doSomething()
CheckedRunnable restrictedCall = RateLimiter
.decorateCheckedRunnable(rateLimiterWithDefaultConfig, backendService::doSomething);
Try.run(restrictedCall)
.onFailure((RequestNotPermitted throwable) -> LOG.info("Wait before call it again :)"));
除了可以封装 CheckedRunnable,还可以封装Callable、Supplier、Runnable、Consumer、CheckedSupplier、CheckedConsumer、CompletionStage类型。
spring注解实现流控
application.yml
resilience4j.ratelimiter:
instances:
backendA:
limitForPeriod: 10
limitRefreshPeriod: 1s
timeoutDuration: 0
registerHealthIndicator: true
eventConsumerBufferSize: 100
backendB:
limitForPeriod: 6
limitRefreshPeriod: 500ms
timeoutDuration: 3s
代码:
@RateLimiter(name = "backendA",fallbackMethod = "fallback" )
public Mono<String> method(String param1) {
return Mono.error(new NumberFormatException());
}
private Mono<String> fallback(String param1, IllegalArgumentException e) {
return Mono.just("test");
}
private Mono<String> fallback(String param1, RuntimeException e) {
return Mono.just("test");
}
与Feign集成
依赖:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.6.1</version>
</dependency>
@FeignClient(name = "x")
interface TestClient {
@GetMapping("/test1")
@RateLimiter(name = "x", fallbackMethod = "m1")
String test1();
@GetMapping("/test2")
@RateLimiter(name = "x", fallbackMethod = "m2")
String test2();
default String m1(Exception e){
// ....
return "x";
}
default String m2(Exception e){
// ....
return "x";
}
}
更多
spring cloud resilience4j-retry 重试
spring cloud resilience4j - Bulkhead 线程隔离 并发控制
spring cloud Resilience4j - 熔断器 CircuitBreaker
spring cloud resilience4j - RateLimiter 流控