Soul网关源码学习系列之【Hystrix插件】

Hystrix简介

  • Hystrix的设计目标
    • 对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的
    • 阻止故障的连锁反应
    • 快速失败并迅速恢复
    • 回退并优雅降级
    • 提供近实时的监控与告警
  • Hystrix遵循的设计原则
    • 防止任何单独的依赖耗尽资源(线程)
    • 过载立即切断并快速失败,防止排队
    • 尽可能提供回退以保护用户免受故障
    • 使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
    • 通过近实时的指标,监控和告警,确保故障被及时发现
    • 通过动态修改配置属性,确保故障及时恢复
    • 防止整个依赖客户端执行失败,而不仅仅是网络通信
  • Hystrix如何实现这些设计目标
    • 使用命令模式将所有对外部服务(或依赖关系)的调用包装在HystrixCommand或HystrixObservableCommand对象中,并将该对象放在单独的线程中执行
    • 每个依赖都维护着一个线程池(或信号量),线程池被耗尽则拒绝请求(而不是让请求排队)
    • 记录请求成功,失败,超时和线程拒绝
    • 服务错误百分比超过了阈值,熔断器开关自动打开,一段时间内停止对该服务的所有请求
    • 请求失败,被拒绝,超时或熔断时执行降级逻辑
    • 近实时地监控指标和配置的修改
  • 通过上述的描述,大致能知道Hystrix是干什么的,能起到什么作用。
  • 对于Hystrix不了解的同学可以看这篇文章:Hystrix原理与实战

示例演示

  • 启动soul-adminsoul-bootstrap
    需要注意的是soul-bootstrap网关的 pom.xml 文件中添加 hystrix的支持。
      <!-- soul hystrix plugin start-->
      <dependency>
          <groupId>org.dromara</groupId>
          <artifactId>soul-spring-boot-starter-plugin-hystrix</artifactId>
           <version>${last.version}</version>
      </dependency>
      <!-- soul hystrix plugin end-->
    
  • soul-admin –> 插件管理 –> hystrix,设置为开启。并且在hystrix插件处设置选择其和规则
    在这里插入图片描述
    在这里插入图片描述
    • 跳闸最小请求数量 :最小的请求量,至少要达到这个量才会触发熔断
    • 错误百分比阀值 : 这段时间内,发生异常的百分比。
    • 跳闸休眠时间(ms) :熔断以后恢复的时间。
    • 分组Key: 一般设置为:contextPath,默认为divide的selector名。
    • 命令Key: 一般设置为具体的 路径接口,默认为divide的规则名。
    • 失败降级URL:失败后调用的的url
    • 注:为了演示效果,把并发量和容错阈值都设置的比较小
  • 为了演示高并发,使用Superbenchmarker如下命令:
    sb -c 10 -N 10 -u http://localhost:9195/http/order/findById?id=2
  • 然后看控制台的log,发现Hystrix起作用了
    2021-02-01 22:56:24.569  INFO 14096 --- [work-threads-42] o.d.soul.plugin.base.AbstractSoulPlugin  : hystrix selector success match , selector name :testH
    2021-02-01 22:56:24.569  INFO 14096 --- [work-threads-43] o.d.soul.plugin.base.AbstractSoulPlugin  : hystrix selector success match , selector name :testH
    2021-02-01 22:56:24.569 ERROR 14096 --- [work-threads-41] o.d.soul.plugin.hystrix.HystrixPlugin    : hystrix execute have circuitBreaker is Open! groupKey:/http,commandKey:/order/findById
    2021-02-01 22:56:24.569  INFO 14096 --- [work-threads-42] o.d.soul.plugin.base.AbstractSoulPlugin  : hystrix rule success match , rule name :1
    2021-02-01 22:56:24.569  INFO 14096 --- [work-threads-43] o.d.soul.plugin.base.AbstractSoulPlugin  : hystrix rule success match , rule name :1
    2021-02-01 22:56:24.569 ERROR 14096 --- [work-threads-42] o.d.soul.plugin.hystrix.HystrixPlugin    : hystrix execute have circuitBreaker is Open! groupKey:/http,commandKey:/order/findById
    2021-02-01 22:56:24.569 ERROR 14096 --- [work-threads-43] o.d.soul.plugin.hystrix.HystrixPlugin    : hystrix execute have circuitBreaker is Open! groupKey:/http,commandKey:/order/findById
    

代码跟踪

通过上面的log或者根据项目的结构,我们可以定位到soul-plugin-hystrixHystrixPlugin这个类,看一下它的doExecute方法

	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;
        // 从当前web请求匹配上的规则取出熔断配置
        final HystrixHandle hystrixHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), HystrixHandle.class);
        if (StringUtils.isBlank(hystrixHandle.getGroupKey())) {
            hystrixHandle.setGroupKey(Objects.requireNonNull(soulContext).getModule());
        }
        if (StringUtils.isBlank(hystrixHandle.getCommandKey())) {
            hystrixHandle.setCommandKey(Objects.requireNonNull(soulContext).getMethod());
        }
        Command command = fetchCommand(hystrixHandle, exchange, chain);
        return Mono.create(s -> {
            Subscription sub = command.fetchObservable().subscribe(s::success,
                    s::error, s::success);
            s.onCancel(sub::unsubscribe);
            // 断路器 判断是否熔断
            if (command.isCircuitBreakerOpen()) {
                log.error("hystrix execute have circuitBreaker is Open! groupKey:{},commandKey:{}", hystrixHandle.getGroupKey(), hystrixHandle.getCommandKey());
            }
        }).doOnError(throwable -> {
            log.error("hystrix execute exception:", throwable);
            exchange.getAttributes().put(Constants.CLIENT_RESPONSE_RESULT_TYPE, ResultEnum.ERROR.getName());
            chain.execute(exchange);
        }).then();
    }
  • 上面这个方法通过execute()方法,以同步堵塞方式执行run(),只支持接收一个值对象。hystrix会从线程池中取一个线程来执行run(),并等待返回值。
    public Observable<Void> fetchObservable() {
        return RxReactiveStreams.toObservable(this.execute());
    }
    

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值