使用Hystrix实现熔断

在使用Hystrix实现熔断的过程中遇到了两个问题

1、在修改了熔断配置之后不生效的问题
2、熔断后不恢复的问题

对于第一个问题,查看hystrix源码可以看到,如果有缓存配置是优先使用的缓存的,因此如果配置更新,必须要更新缓存,不能使用Hystrix.reset()方法来更新缓存,这个方法清理全局缓存,会影响其他commandkey的熔断状态。

public static HystrixCircuitBreaker getInstance(HystrixCommandKey key, HystrixCommandGroupKey group, HystrixCommandProperties properties, HystrixCommandMetrics metrics) {
            // this should find it for all but the first time
            HystrixCircuitBreaker previouslyCached = circuitBreakersByCommand.get(key.name());
            if (previouslyCached != null) {
                return previouslyCached;
            }

官方提供的方法是通过archaius动态更新:https://github.com/Netflix/Hystrix/wiki/Configuration

Hystrix uses Archaius for the default implementation of properties for configuration.

实现接口com.netflix.config.PolledConfigurationSource,将对应的commandkey通过形如下面的key来放入poll方法响应的map中,hystrix会根据这个key自动更新缓存

hystrix.command.HystrixCommandKey.execution.isolation.thread.timeoutInMilliseconds

第二个问题经过debughystrix源码发现是由于,使用了响应式的调用,hystrix使用的是V1版本的rxjava,而项目使用的是V3版本的rxjava,在V3转V1后响应给hystrixcircuitbreaker时,hystrix没有收到oncomplete事件,导致没有在断路器半开状态时调用成功关闭断路器。

在com.netflix.hystrix.AbstractCommand类中实现了断路器的控制逻辑:

可以看到在onCompleted的观察者逻辑中会将断路器markSuccess

private Observable<R> executeCommandAndObserve(final AbstractCommand<R> _cmd) {
        final HystrixRequestContext currentRequestContext = HystrixRequestContext.getContextForCurrentThread();

        final Action1<R> markEmits = new Action1<R>() {
            @Override
            public void call(R r) {
                if (shouldOutputOnNextEvents()) {
                    executionResult = executionResult.addEvent(HystrixEventType.EMIT);
                    eventNotifier.markEvent(HystrixEventType.EMIT, commandKey);
                }
                if (commandIsScalar()) {
                    long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                    eventNotifier.markCommandExecution(getCommandKey(), properties.executionIsolationStrategy().get(), (int) latency, executionResult.getOrderedList());
                    eventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey);
                    executionResult = executionResult.addEvent((int) latency, HystrixEventType.SUCCESS);
                    circuitBreaker.markSuccess();
                }
            }
        };

        final Action0 markOnCompleted = new Action0() {
            @Override
            public void call() {
                if (!commandIsScalar()) {
                    long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                    eventNotifier.markCommandExecution(getCommandKey(), properties.executionIsolationStrategy().get(), (int) latency, executionResult.getOrderedList());
                    eventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey);
                    executionResult = executionResult.addEvent((int) latency, HystrixEventType.SUCCESS);
                    circuitBreaker.markSuccess();
                }
            }
        };

目前想到的解决办法是一种是在接收调用服务响应时blockingfirst(),但是这样会导致异步调用变成同步,还有一种是在调用服务的Observable的onnext方法中添加onCompleted事件,来通知hystrix调用服务接收到了complete事件,但是这样就只能接收到单个onNext事件,两种都有缺点,还有想到更好的解决办法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值