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

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 步,执行成功就返回结果,执行的结果数据会上报给断路器,断路器会根据上报的数据来判断断路器是否打开。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
layui-soul-table 是一款基于layui框架开发的用于展示数据的表格插件。要快速隐藏列,可以通过以下步骤进行操作: 1. 首先,确保已加载layui和layui-soul-table的相关资源文件。可以在页面引入layui和layui-soul-table的CSS和JS文件,例如: ```html <link rel="stylesheet" href="path/to/layui/css/layui.css"> <link rel="stylesheet" href="path/to/layui-soul-table/soulTable.css"> <script src="path/to/layui/layui.js"></script> <script src="path/to/layui-soul-table/soulTable.js"></script> ``` 2. 在HTML页面,创建一个具有固定id的表格元素,例如: ```html <table id="demo" lay-filter="test"></table> ``` 3. 在JavaScript代码,使用layui-soul-table的自定义参数来创建表格,并设置隐藏列的显示属性。例如: ```javascript layui.use(['table', 'soulTable'], function(){ var table = layui.table; var soulTable = layui.soulTable; table.render({ elem: '#demo', url: '/api/data', // 数据接口 cols: [[ {field:'id', title: 'ID'}, {field:'name', title: '名称'}, {field:'age', title: '年龄'}, // 其他列 {field:'操作', title: '操作', toolbar: '#barDemo', width: 150} // 需要隐藏的列 ]], }); soulTable.on('filter(test)', function(data){ // 判断隐藏列的显示状态 var isHide = data.isHide; if(isHide){ $('#demo .layui-table-view .layui-table').find('[data-field="操作"]').hide(); }else{ $('#demo .layui-table-view .layui-table').find('[data-field="操作"]').show(); } }); }); ``` 通过以上步骤,就可以在 layui-soul-table 快速隐藏指定的列。具体实现是通过监听"filter(test)"事件,判断隐藏列的状态,然后利用jQuery的hide()和show()方法来控制目标列的显示属性。使用这种方法,我们可以方便地实现快速隐藏列功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值