作用:
resilience4j是用来进行限流和熔断的。
引入:
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-spring-boot-starter-plugin-resilience4j</artifactId>
<version>${project.version}</version>
</dependency>
熔断器配置:
后台启用resilience4j插件
control behavior timeout (ms)(timeoutDurationRate):等待获取令牌的超时时间,单位ms,默认值:5000。
token filling period (ms)(limitRefreshPeriod):刷新令牌的时间间隔,单位ms,默认值:500。
token filling number(limitForPeriod):每次刷新令牌的数量,默认值:50。
circuit enable(circuitEnable):是否开启熔断,0:关闭,1:开启,默认值:0。
circuit timeout (ms)(timeoutDuration):熔断超时时间,单位ms,默认值:30000。
fallback uri(fallbackUri):降级处理的uri。
sliding window size(slidingWindowSize):滑动窗口大小,默认值:100。
sliding window type(slidingWindowType):滑动窗口类型,0:基于计数,1:基于时间,默认值:0。
enabled error minimum calculation threshold(minimumNumberOfCalls):开启熔断的最小请求数,超过这个请求数才开启熔断统计,默认值:100。
degrade opening duration(waitIntervalFunctionInOpenState):熔断器开启持续时间,单位ms,默认值:10。
half open threshold(permittedNumberOfCallsInHalfOpenState):半开状态下的环形缓冲区大小,必须达到此数量才会计算失败率,默认值:10。
degrade failure rate(failureRateThreshold):错误率百分比,达到这个阈值,熔断器才会开启,默认值50。
automaticTransitionFromOpenToHalfOpenEnabled:是否自动从open状态转换为half-open状态,,true:是,false:否,默认值:false。
源码解析
进入到Resilience4JPlugin
的doExecute
方法:
@Override
protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
assert soulContext != null;
// 将resilience4j的rule配置转为Resilience4JHandle对象
Resilience4JHandle resilience4JHandle = GsonUtils.getGson().fromJson(rule.getHandle(), Resilience4JHandle.class);
// 如果开启断路器,执行combined方法
if (resilience4JHandle.getCircuitEnable() == 1) {
return combined(exchange, chain, rule);
}
// 如果不开启断路器,执行rateLimiter方法
return rateLimiter(exchange, chain, rule);
}
1)将后台配置的断路器规则转为
Resilience4JHandle
对象2)判断断路器是否开启:
- 开启,执行combined方法(多种操作:熔断、限流)
- 未开启,执行rateLimiter方法(限流)
熔断限流的配置类
public class Resilience4JBuilder {
/**
* build.
*
* @param ruleData the ruleData
* @return Resilience4JConf
*/
public static Resilience4JConf build(final RuleData ruleData) {
Resilience4JHandle handle = GsonUtils.getGson().fromJson(ruleData.getHandle(), Resilience4JHandle.class);
CircuitBreakerConfig circuitBreakerConfig = null;
if (handle.getCircuitEnable() == 1) {
// 熔断配置类
circuitBreakerConfig = CircuitBreakerConfig.custom()
// 请求调用失败,存储异常记录的集合
.recordExceptions(Throwable.class, Exception.class)
// 熔断器打开的失败阈值或半开状态使用的同一个失败率阈值
.failureRateThreshold(handle.getFailureRateThreshold())
// 是否自动从打开到半开,当waitDurationInOpenState时间一过,是否自动从OPEN切换到HALF_OPEN
// true:waitDurationInOpenState到期后open自动变为half_open
// false: 得等到再有请求后状态才会变为half_open,否则即使waitDurationInOpenState到期状态依然是open
.automaticTransitionFromOpenToHalfOpenEnabled(handle.getAutomaticTransitionFromOpenToHalfOpenEnabled())
// 滑动窗口类型,默认为基于计数的 COUNT_BASED
.slidingWindow(handle.getSlidingWindowSize(), handle.getMinimumNumberOfCalls(),
handle.getSlidingWindowType() == 0
? CircuitBreakerConfig.SlidingWindowType.COUNT_BASED
: CircuitBreakerConfig.SlidingWindowType.TIME_BASED).waitIntervalFunctionInOpenState(IntervalFunction
.of(Duration.ofSeconds(handle.getWaitIntervalFunctionInOpenState() / 1000)))
// 熔断器半开时的缓冲区大小,会限制线程的并发量(只允许ringBufferSizeInHalfOpenState个并发),
// 例如缓冲区为10则每次只会允许10个请求调用后端服务
// 之所以能限制并发,CircuitBreakerStateMachine使用了AtomicInteger:this.permittedNumberOfCalls = new AtomicInteger(permittedNumberOfCallsInHalfOpenState);
.permittedNumberOfCallsInHalfOpenState(handle.getPermittedNumberOfCallsInHalfOpenState()).build();
}
// 超时配置
TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(handle.getTimeoutDuration() / 1000)).build();
// 限流器配置
RateLimiterConfig rateLimiterConfig = RateLimiterConfig.custom()
// 周期内允许通过的请求数量。 默认:50
.limitForPeriod(handle.getLimitForPeriod())
// 获取授权操作的超时时间。 默认:5秒
.timeoutDuration(Duration.ofSeconds(handle.getTimeoutDurationRate() / 1000))
// 限流周期时长。 默认:500纳秒
.limitRefreshPeriod(Duration.ofNanos(handle.getLimitRefreshPeriod() * 1000000)).build();
return new Resilience4JConf(Resilience4JHandler.getResourceName(ruleData), handle.getFallbackUri(), rateLimiterConfig, timeLimiterConfig, circuitBreakerConfig);
}
}
circuitBreakerConfig:熔断配置类
TimeLimiterConfig:超时配置
RateLimiterConfig:限流器配置
rateLimiter方法
private Mono<Void> rateLimiter(final ServerWebExchange exchange, final SoulPluginChain chain, final RuleData rule) {
return ratelimiterExecutor.run(
chain.execute(exchange), fallback(ratelimiterExecutor, exchange, null), Resilience4JBuilder.build(rule))
.onErrorResume(throwable -> ratelimiterExecutor.withoutFallback(exchange, throwable));
}
// 限流类
public class RateLimiterExecutor implements Executor {
@Override
public <T> Mono<T> run(final Mono<T> toRun, final Function<Throwable, Mono<T>> fallback, final Resilience4JConf conf) {
// 通过限流配置,创建限流类
RateLimiter rateLimiter = Resilience4JRegistryFactory.rateLimiter(conf.getId(), conf.getRateLimiterConfig());
Mono<T> to = toRun.transformDeferred(RateLimiterOperator.of(rateLimiter));
if (fallback != null) {
return to.onErrorResume(fallback);
}
return to;
}
}
通过 ratelimiterExecutor的run方法进行限流的一些处理,以及错误处理onErrorResume
combined方法
private Mono<Void> combined(final ServerWebExchange exchange, final SoulPluginChain chain, final RuleData rule) {
Resilience4JConf conf = Resilience4JBuilder.build(rule);
return combinedExecutor.run(
chain.execute(exchange).doOnSuccess(v -> {
if (exchange.getResponse().getStatusCode() != HttpStatus.OK) {
HttpStatus status = exchange.getResponse().getStatusCode();
exchange.getResponse().setStatusCode(null);
throw new CircuitBreakerStatusCodeException(status);
}
}), fallback(combinedExecutor, exchange, conf.getFallBackUri()), conf);
}
public class CombinedExecutor implements Executor {
@Override
public <T> Mono<T> run(final Mono<T> run, final Function<Throwable, Mono<T>> fallback, final Resilience4JConf resilience4JConf) {
// 限流类
RateLimiter rateLimiter = Resilience4JRegistryFactory.rateLimiter(resilience4JConf.getId(), resilience4JConf.getRateLimiterConfig());
// 断路器类
CircuitBreaker circuitBreaker = Resilience4JRegistryFactory.circuitBreaker(resilience4JConf.getId(), resilience4JConf.getCircuitBreakerConfig());
// CircuitBreakerOperator.of(circuitBreaker):返回一个CircuitBreakerOperator的Publisher
Mono<T> to = run.transformDeferred(CircuitBreakerOperator.of(circuitBreaker))
// RateLimiterOperator.of(rateLimiter):返回一个RateLimiterOperator的Publisher
.transformDeferred(RateLimiterOperator.of(rateLimiter))
// 设置超时时间
.timeout(resilience4JConf.getTimeLimiterConfig().getTimeoutDuration())
// 错误处理
.doOnError(TimeoutException.class, t -> circuitBreaker.onError(
resilience4JConf.getTimeLimiterConfig().getTimeoutDuration().toMillis(),
TimeUnit.MILLISECONDS,
t));
if (fallback != null) {
to = to.onErrorResume(fallback);
}
return to;
}
}
通过 combinedExecutor的run方法进行断路器的一些处理
验证
正常请求:
熔断:
过一段时间请求,又恢复正常。