Soul源码解析(17)-Soul网关hystrix熔断插件源码解读及hystrix、resilienc4j、sentinel对比

一、目标

1、解读熔断插件关键代码,对比各熔断插件;

2、排查上一节使用过程中遇到的问题;

二、内容

2.1背景

上一节我们一起学习了Soul网关中hystrix插件的使用,并且在使用的过程中发现了一些问题,这一节我们就一起来学习一下hystrix熔断插件的关键代码实现。对比hystrix插件与其他几个熔断插件。排查使用过程中遇到的问题。

有关hystrix插件的使用,可以参考上一节的内容:

Soul网关现在支持熔断的插件有:

  • hystrix
  • resilienc4j
  • sentinel

2.2 HystrixPlugin插件分析

  • HystrixPlugin继承了AbstractSoulPlugin类,重写了doExecute()方法。插件前面的调用链已经分析过了,可以参考之前的分析:

divide插件分析:https://blog.csdn.net/qq_38314459/article/details/112760726

@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;
        //获取rule规则配置数据
        final HystrixHandle hystrixHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), HystrixHandle.class);
        //处理groupKey和commandKey为空的方法,如果groupKey为空,则默认设置为contextPath
        if (StringUtils.isBlank(hystrixHandle.getGroupKey())) {
            hystrixHandle.setGroupKey(Objects.requireNonNull(soulContext).getModule());
        }
        //如果commandKey为空,默认设置为具体的请求路径
        if (StringUtils.isBlank(hystrixHandle.getCommandKey())) {
            hystrixHandle.setCommandKey(Objects.requireNonNull(soulContext).getMethod());
        }
        //创建hystrixCommand
        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();
    }
  • fetchCommand()方法分析,在创建command的过程中,会去判断是信号量还是线程,根据不同的类型创建Command
private Command fetchCommand(final HystrixHandle hystrixHandle, final ServerWebExchange exchange, final SoulPluginChain chain) {
        if (hystrixHandle.getExecutionIsolationStrategy() == HystrixIsolationModeEnum.SEMAPHORE.getCode()) {
            return new HystrixCommand(HystrixBuilder.build(hystrixHandle),
                exchange, chain, hystrixHandle.getCallBackUri());
        }
        return new HystrixCommandOnThread(HystrixBuilder.buildForHystrixCommand(hystrixHandle),
            exchange, chain, hystrixHandle.getCallBackUri());
    }

HystrixCommand类分析,HystrixCommand继承了HystrixObservableCommand,实现了Command接口。这里面主要的方法是fetchObservable()方法:

@Override
    public Observable<Void> fetchObservable() {
        return this.toObservable();
    }

每次执行的时候加上监听,其中this.execute()方法调用的hystrix自身提供的方法;

如果达到熔断的条件,会调用Command里面的doFallBack方法:

 default Mono<Void> doFallback(ServerWebExchange exchange, Throwable exception) {
        if (Objects.isNull(getCallBackUri())) {
            Object error;
            error = generateError(exchange, exception);
            return WebFluxResultUtils.result(exchange, error);
        }
        DispatcherHandler dispatcherHandler =
            SpringBeanUtils.getInstance().getBean(DispatcherHandler.class);
        ServerHttpRequest request = exchange.getRequest().mutate().uri(getCallBackUri()).build();
        ServerWebExchange mutated = exchange.mutate().request(request).build();
        return dispatcherHandler.handle(mutated);
    }

2.3 熔断插件对比

在这里插入图片描述

Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性;可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况;Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合;Sentinel 提供简单易用、完善的 SPI 扩展接口,可以通过扩展接口来定制业务逻辑。

Hystrix是一个延迟和容错库,旨在隔离远程系统、服务和第三方库的访问点,停止级联故障,并在故障不可避免的复杂分布式系统中实现恢复能力;

Resilience4j是一个为Java8和函数式编程设计的容错库。提供高阶函数(decorators)来增强任何功能接口、lambda表达式或方法引用,包括断路器、速率限制器、重试或隔板。可以在任何函数接口、lambda表达式或方法引用上堆叠多个装饰器。优点是您可以选择所需的装饰器,而无需其他任何东西。

2.4 上一节报错原因分析

报错是由于没有找到divide插件的upstream造成的

在这里插入图片描述

打开soul-admin控制台,发现divide插件选择器的配置的确为空了

在这里插入图片描述

三、总结

Soul网关支持hystrix、sentinel、resilienc4j三个熔断插件,着重分析了hystrix插件的源码。简单对比了三个插件的区别和功能差别。三个插件的使用,有共同的地方,也有差异的部分,一起对比来看会更有收获。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值