Soul网关(十四)---- Soul 中的容错保护(1)

本文详细介绍了Soul框架中如何使用Hystrix进行容错保护,包括Hystrix的简介、Soul中的Hystrix插件实现、熔断规则设置以及工作原理。通过设置插件优先级、断路器逻辑等,实现了对微服务请求的熔断处理,确保系统稳定性。

Soul 中的容错保护

Hystrix

Hystrix简介

Hystrix 由 Netflix 发布的针对微服务分布式系统的熔断保护中间件。

soul 中的 Hystrix 插件

在「反应式编程&插件调用链」一文中,已经分析过插件的调用链,请求进来会默认走以下 3 个前置插件,其中就包括 Hystrix 插件

HystrixPlugin
Resilience4JPlugin
SentinelPlugin

这里设置了插件优先级:

    /**
     * Hystrix plugin enum.
     */
    HYSTRIX(45, 0, "hystrix"),

    /**
     * Sentinel plugin enum.
     */
    SENTINEL(45, 0, "sentinel"),

    /**
     * Resilence4J plugin enum.
     */
    RESILIENCE4J(45, 0, "resilience4j"),

请求经过这3个插件时都会执行 AbstractSoulPlugin 类的 execute() 方法:

public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
		// 获取插件名称
    String pluginName = named();
    // 根据插件名获取该插件的基本数据,如 PluginData(id=9, name=hystrix, config=null, role=0, enabled=true)
    final PluginData pluginData = BaseDataCache.getInstance().obtainPluginData(pluginName);
  	// 要在 soul-admin 中将插件打开,否则web请求不会被此插件处理 
    if (pluginData != null && pluginData.getEnabled()) {
      	// 选择器数据
        final Collection<SelectorData> selectors = BaseDataCache.getInstance().obtainSelectorData(pluginName);
        if (CollectionUtils.isEmpty(selectors)) {
            return handleSelectorIsNull(pluginName, exchange, chain);
        }
        final SelectorData selectorData = matchSelector(exchange, selectors);
        if (Objects.isNull(selectorData)) {
            return handleSelectorIsNull(pluginName, exchange, chain);
        }
        selectorLog(selectorData, pluginName);
      	// 规则列表
        final List<RuleData> rules = BaseDataCache.getInstance().obtainRuleData(selectorData.getId());
        if (CollectionUtils.isEmpty(rules)) {
            return handleRuleIsNull(pluginName, exchange, chain);
        }
        RuleData rule;
        if (selectorData.getType() == SelectorTypeEnum.FULL_FLOW.getCode()) {
            //get last
            rule = rules.get(rules.size() - 1);
        } else {
            rule = matchRule(exchange, rules);
        }
        if (Objects.isNull(rule)) {
            return handleRuleIsNull(pluginName, exchange, chain);
        }
        ruleLog(rule, pluginName);
      	// 熔断逻辑 
        return doExecute(exchange, chain, selectorData, rule);
    }
    return chain.execute(exchange);
}

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;
  	// 从当前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())) {
      	// 没有配置 ‘命令Key’ 时,设置一个默认的
        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();
}
Hystrix处理详解:
  • 跳闸最小请求数量 :最小的请求量,至少要达到这个量才会触发熔断

  • 错误半分比阀值 : 这段时间内,发生异常的百分比。

  • 最大并发量 : 最大的并发量

  • 跳闸休眠时间(ms) :熔断以后恢复的时间。

  • 分组Key: 一般设置为:contextPath

  • 命令Key: 一般设置为具体的 路径接口。

可以在 soul-admin 的 hystrix 插件中设置熔断规则:

image-20210130001240157

总结

Hystrix 的工作原理

在这里插入图片描述

第 1 步:构建了一个 HystrixCommand 或者 HystrixObservableCommand 对象,将请求包装到 Command 对象之中;

第 2 步:执行构建好的命令;

第 3 步:判断当前请求是否有缓存,如果有缓存,就直接返回缓存内容。

第 4 步:判断断路器是否处于打开的状态,如果打开,那么 Hystrix 就不再会去执行命令,直接跳到第 8 步,获取 fallback 方法,执行回退逻辑;

如果断路器没有打开,则继续执行第 5 步:判断是否能够执行该命令,如果是线程池隔离模式,会判断线程池队列的容量,如果是信号量隔离模式,会判断信号量的值是否已被使用完。如果线程池和信号量都满了,那么请求不会再执行,直接跳到第 8 步。

如果容量满足执行条件,则继续第 6 步,执行 HystrixObservableCommand.construct() 或者 HystrixCommand.run() 方法,正在执行的请求逻辑就封装在 construct() 或者 run() 方法中。

在请求执行过程中,如果出现异常或超时等情况,则直接到第 8 步,执行成功就返回结果,执行的结果数据会上报给断路器,断路器会根据上报的数据来判断断路器是否打开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值