目录
1. AbstractCommand
因为hystrix的命令执行都是基于RXjava的,所以在看源码之前一定要先了解RXjava。
HystrixCommand继承了AbstractCommand,HystrixCommand主要是提供了更多的构造函数和构造参数建造者以及最终调用run()实现用户业务,而AbstractCommand中就是要实现隔离、熔断等核心功能。
2. 超时入口
hystrix超时入口是在AbstractCommand类中。是在com.netflix.hystrix.AbstractCommand.executeCommandAndObserve方法中进行是否开启超时熔断的判断的。
而这个executionTimeoutEnabled配置是从properties属性中取的,可以看到这个属性的值来源于com.netflix.hystrix.HystrixCommandProperties#executionTimeoutEnabled。
com.netflix.hystrix.HystrixCommandProperties#executionTimeoutEnabled又是在构造HystrixCommandProperties对象时通过构造函数初始化的
this.executionTimeoutEnabled = getProperty(propertyPrefix, key, “execution.timeout.enabled”, builder.getExecutionTimeoutEnabled(), default_executionTimeoutEnabled);
因此就能知道,这个属性的赋值是由我们代码中通过继承com.netflix.hystrix.HystrixObservableCommand类,传入com.netflix.hystrix.HystrixCommandProperties.Setter对象初始化的
所以在代码中通过setter.withExecutionTimeoutEnabled(true);来打开超时熔断的开关。
3. 判断超时的逻辑
当我们的代码执行的时候会回调HystrixObservableTimeoutOperator.call()方法,超时的逻辑主要在这个方法中。
4. 创建一个监听器
监听器就是来监听我们的command是否超时
5. TimerListener.tick()入线程池
final Reference tl = HystrixTimer.getInstance().addTimerListener(listener);
获取单例的HystrixTimer,这里面维护了一个线程池ScheduledThreadPoolExecutor
构建了一个线程池ScheduledThreadPoolExecutor,默认的coreSize=8。
ScheduledThreadPoolExecutor的状态管理、入队操作、拒绝操作等都是继承于 ThreadPoolExecutor;ScheduledThreadPoolExecutor 主要是提供了周期任务和延迟任务相关的操作;
HystrixTimer.addTimerListener() 这个方法会把之前创建好的TimerListener加入HystrixTimer中,并把TimerListener.tick()封装为一个Runnable扔到线程池里。
listener.getIntervalTimeInMilliseconds()这个参数就是我们设置的超时时间,所以这个任务会在我们设置的超时时间(hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds)之后运行,来判断timedOutStatus的状态。
6. 执行业务逻辑
若执行时间超过(hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds),command的TimedOutStatus状态则为NOT_EXECUTED,会在后续TimerListener.tick()方法内部执行if判断的时候,进入方法内部。
7. TimerListener.tick()方法
通过tick()方法判断我们的任务是否超时。
判断当前command的TimedOutStatus是否是NOT_EXECUTED,如果是,则认为超时了,就把状态设置为TIMED_OUT,并抛出HystrixTimeoutException异常,如果不是的话,则什么都不做。
8. HystrixTimeoutException异常
9. 清理任务
f.cancel()就是清理Runnable的任务