Hystrix使用与原理浅析

本文介绍 Hystrix 断路器的功能与工作原理,包括优雅处理服务失效、快速恢复、服务隔离等特性。文章还提供了原生方式及 Spring Cloud 方式的使用示例,并深入探讨了 RXJava 在 Hystrix 中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的

优雅地处理服务失效,防止雪崩

功能

  • 熔断器,统计服务执行情况,达到熔断条件时直接进行降级处理。
  • 快速恢复,在熔断后一定时间会尝试半开,尝试重新请求。
  • 服务隔离,服务可以使用单独的线程池,失效时无法影响其余服务。
  • 快速失败。可以设置时延,以达到快速失效,不会一直耗着资源。
  • 监控面板

使用方式

原生方式:

(1)继承HystrixCommand/HystrixObservableCommand
(2)重写run()/construct()
(3)实例化
(4)执行execute()/queue()/observe()/toObservable()。

public class LblCommand extends HystrixCommand<String>{
    protected LblCommand() {
    	super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
    }
    
    @Override
    protected String run() throws Exception {
    	throw new Exception();
    }
    
    @Override
    protected String getFallback() {
    	return "fallback";
    }
}
Spring cloud方式:
1. 创建项目,包含hystrix依赖
<dependency>	
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.主类中开启熔断器
@SpringBootApplication
@EnableCircuitBreaker
public class HystrixApplication {
    public static void main(String[] args) {
    	SpringApplication.run(HystrixApplication.class, args);
    }
}
3.使用注解声明HystrixCommand,注意不可以在同一个类中调用HystrixCommand注解的方法,否则不会生效。
@Component
public class LblCommand2 {
    @HystrixCommand(fallbackMethod = "myfallback",commandProperties = {
    	@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")})
    String testHystrix(int i) throws Exception{
        System.out.println(new Date().getSeconds() + ":tried");
        if(i == 0){
        	return "success";
        }
        throw new Exception();
    }
    @HystrixCommand
    String myfallback(int i){
        return "fallback!";
    }
}
4. 更多的commandProperties可以查看HystrixCommandProperties这个类,有详细的说明和默认值。

原理

RXJava

在看Hystrix的时候会发现里面用到了大量的RXJava,这里分享一篇不错的博客https://www.jianshu.com/p/88aacbed8aa5

科普下RXJava。首先,它实现了基本的观察者模式。
观察者模式中有两种角色,Observable和Subscriber,就是被观察者和观察者。
在RXJava中:
(1)Observable的call方法就是被观察者主要逻辑。
(2)观察者需要实现一些回调方法,如onSuccess,onError
(3)在调用subscribe方法建立绑定关系时,将会触发被观察者的call方法,运行主要逻辑,并在运行过程中通过回调通知Subscriber。

其次就是RXJava的是链式调用,如:

//以下为伪代码
new Observable().doOnSuccess().doOnFail().subsribeOn(scheduler)

每一次调用都会根据上一个Observable封装一下生成新的Observable,新的Observable会在原来的基础上增加一些逻辑。

当声明完这一切后,所有方法都不会执行,只有调用subscribe,触发最后一个Observable的call方法,然后它又触发倒数第二个的call方法,一直触发到第一个的call方法。

当理解完这个,再去看hystrix的源码会清晰很多。

hystrix主要流程

观察HystrixCommand的queue方法,跟踪Observable的封装过程,可以得出hystrix的主要流程。

(1)检查circuitBreaker
(2)检查信号量
(3)检查线程池
(4)执行逻辑
(5)是否有异常
(6)是否超时
(7)一旦1/2/3/5/6失败则执行fallback方法

信号量/线程池

我们可以根据参数executionIsolationStrategy设置使用THREAD或SEMAPHORE模式。

信号量模式

无论如何,程序都会去获取信号量,如果设为信号量模式,此时会根据最大并发数创建信号量,当并达到并发数时,tryAcquire就会失败,则执行fallback。

线程模式

设为线程模式,获取信号量时会返回TryableSemaphoreNoOp,该对象的tryAcquire方法永远为true,相当于忽略信号量检查。

完成信号量检查后,会为Observerable再封装一层,增加线程异步执行的逻辑。

//位于AbstractCommand的executeCommandWithSpecifiedIsolation方法
subscribeOn(threadPool.getScheduler(new Func0<Boolean>() {
    @Override
    public Boolean call() {
        return properties.executionIsolationThreadInterruptOnTimeout().get() && _cmd.isCommandTimedOut.get() == TimedOutStatus.TIMED_OUT;
    }
}));

在这里,每个CommandKey会使用单独的线程池,使得服务调用可以隔离开来,不会互相影响,但是线程上下文切换会影响效率。

关于线程池的参数可以查看对应的Setter类,会有详细的参数。

超时/异常

超时检查
//位于AbstractCommand的executeCommandAndObserve方法
Observable<R> execution;
if (properties.executionTimeoutEnabled().get()) {
    execution = executeCommandWithSpecifiedIsolation(_cmd)
            .lift(new HystrixObservableTimeoutOperator<R>(_cmd));
} else {
    execution = executeCommandWithSpecifiedIsolation(_cmd);
}

如果配置了检查timeout,会为Observable再一层封装,增加timeout计时器的逻辑。

HystrixTimer.getInstance().addTimerListener(listener);
异常处理
final Func1<Throwable, Observable<R>> handleFallback = new Func1<Throwable, Observable<R>>() {
    @Override
    public Observable<R> call(Throwable t) {
        Exception e = getExceptionFromThrowable(t);
        executionResult = executionResult.setExecutionException(e);
        if (e instanceof RejectedExecutionException) {
            return handleThreadPoolRejectionViaFallback(e);
        } else if (t instanceof HystrixTimeoutException) {
            return handleTimeoutViaFallback();
        } else if (t instanceof HystrixBadRequestException) {
            return handleBadRequestByEmittingError(e);
        } else {
            /*
             * Treat HystrixBadRequestException from ExecutionHook like a plain HystrixBadRequestException.
             */
            if (e instanceof HystrixBadRequestException) {
                eventNotifier.markEvent(HystrixEventType.BAD_REQUEST, commandKey);
                return Observable.error(e);
            }

            return handleFailureViaFallback(e);
        }
    }
};

一旦发生异常,会触发此回调方法,并生成新的FallbackObservable,执行fallback逻辑。

总的来说,就是使用了大量的Observable.defer方法进行延迟绑定,根据逻辑判断生成对应的Observable,并使用这个链式编程的特性增加了成功、失败、超时等回调逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值