【高性能网关soul学习】17. 熔断限流插件之Resilienc4j

【高性能网关soul学习】17. 熔断限流插件之Resilienc4j

本文目标:

  1. 跑通熔断限流插件 Resilienc4j
  2. 分析 Soul 中 Resilienc4j 是如何集成的

官网地址


Resilienc4j

Resilience4j是一个轻量级容错框架,设计灵感来源于Netflix 的Hystrix框架,为函数式编程所设计。

Resilience4j 提供了一组高阶函数(装饰器),包括断路器,限流器,重试,隔离,可以对任何的函数式接口,lambda表达式,或方法的引用进行增强,并且这些装饰器可以进行叠加。这样做的好处是,你可以根据需要选择特定的装饰器进行组合。

在使用时,你不需要引入所有和Resilience4j相关的包,只需要引入所需要的即可。

Soul 中 Resilienc4j 插件启动流程
  • soul-bootstrap 增加 soul-spring-boot-starter-plugin-resilience4j 依赖
    • 依次启动 soul-admin、http测试服务、soul-bootstrap 网关服务
  • 选择器和规则配置
Resilience4JPlugin

Resilience4JPlugin 和其他 plugin 一样,都属于流量插件,因此继承于 AbstractSoulPlugin,因此核心方法为 doExecute

  • admin控制台上的 circuit enable 为 1时,启动熔断功能
final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
    assert soulContext != null;
    Resilience4JHandle resilience4JHandle = GsonUtils.getGson().fromJson(rule.getHandle(), Resilience4JHandle.class);
// 如果配置开启了熔断配置,则走熔断限流的分支
    if (resilience4JHandle.getCircuitEnable() == 1) {
        return combined(exchange, chain, rule);
    }
// 只使用限流的组件
    return rateLimiter(exchange, chain, rule);
}

因为 combined 方法里面包含了rateLimiter的功能,因此我们下面重点分析 combined 方法

  • 首先使用 rule 构建了一个配置信息
    • 创建了熔断器和限流器
  • 然后执行 combinedExecutor 的run方法
    • 里面封装了熔断器、限流器的执行操作,以及对错误的捕获和降级逻辑等
private Mono<Void> combined(final ServerWebExchange exchange, final SoulPluginChain chain, final RuleData rule) {
  // 根据rule配置信息,创建 Resilience4J 相关配置
    Resilience4JConf conf = Resilience4JBuilder.build(rule);
    return combinedExecutor.run(
      // 插件链执行完毕之后执行结果判断逻辑
            chain.execute(exchange).doOnSuccess(v -> {
              ... check 抛出一个异常,后续捕获
              // 降级处理
            }), fallback(combinedExecutor, exchange, conf.getFallBackUri()), conf);
}
// Resilience4JBuilder.java 大致流程
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()
          // 熔断的失败判定:所有的Throwable 和 Exception 都会被判定为失败
                .recordExceptions(Throwable.class, Exception.class)
          // 其他的一些参数配置设置
                ... ;
    }
  // 时间限制配置
    TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
            .timeoutDuration(Duration.ofSeconds(handle.getTimeoutDuration() / 1000)).build();
// 限流组件配置
  RateLimiterConfig rateLimiterConfig = RateLimiterConfig.custom()
            .limitForPeriod(handle.getLimitForPeriod())
            .timeoutDuration(Duration.ofSeconds(handle.getTimeoutDurationRate() / 1000))
            .limitRefreshPeriod(Duration.ofNanos(handle.getLimitRefreshPeriod() * 1000000)).build();
    return new Resilience4JConf(Resilience4JHandler.getResourceName(ruleData), handle.getFallbackUri(), rateLimiterConfig, timeLimiterConfig, circuitBreakerConfig);
}

// CombinedExecutor.java
@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());
    Mono<T> to = run
      // 执行熔断器操作
      .transformDeferred(CircuitBreakerOperator.of(circuitBreaker))
            // 执行限流操作操作
            .transformDeferred(RateLimiterOperator.of(rateLimiter))
            .timeout(resilience4JConf.getTimeLimiterConfig().getTimeoutDuration())
      // 出现错误时,熔断器捕获异常,后续转为各种event进行处理
            .doOnError(...);
  // 降级操作
    if (fallback != null) {
        to = to.onErrorResume(fallback);
    }
    return to;
}

总结

  • Resilienc4j 插件根据开关的打开情况,支持只使用限流配置或者 限流+熔断 两种配置方式
  • Resilienc4j 的API设计非常简单易用
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值