SpringCloud-Hystrix原理与Dubbo整合

Hystrix原理与Dubbo整合

断路器使用命令模式将要执行的目标Tag方法,封装到HystrixCommand中执行(线程池、信号量),为微服务架构提供服务熔断、限流、降级机制的框架工具。
Hystrix提供多种隔离方式:

  • 线程池隔离
  • 信号量隔离
  • 熔断
  • 降级回退

Hystrix防止雪崩效应

  • Hystrix将请求逻辑封装,隔离在单独线程中执行
  • Hystrix有自动超时策略,如果外部请求超过阀值,Hystrix会以快速超时失败处理
  • Hystrix为每一个分组服务,提供一个线程池,当线程池满载时不会线程排队,会直接快速失败
  • Hystrix在管理的服务失效超过一定配置比例时,会自动切断服务一段时间。

Hystrix 工作原理

SpringCloud-Hystrix原理与Dubbo整合_第1张图片
image

执行步骤如下:

    1. 创建HystrixCommand或者HystrixObservableCommand对象,将目标Tag方法封装到命令模式中。
    1. 执行命令execute()、queue()、observe()、toObservable()
    1. 如果请求结果缓存特性开启(不建议开启),并且命中缓存则从缓存获取Observable返回。
    1. 检查熔断状态,如果熔断机制启动,则执行getFallback命令,否则执行这个命令
    1. 检查执行命令的线程池或者信号量是否满载,如果满载则执行getFallback命令
    1. 执行HystrixCommand.run()或HystrixObservableCommand.construct(),如果超时或者执行失败则执行getFallback命令
    1. Hystrix 会将请求成功,失败,被拒绝或超时信息报告给熔断器,熔断器维护一些用于统计数据用的计数器

Circuit Breaker 断路器

HystrixCircuitBreaker断路器实现接口:

public interface HystrixCircuitBreaker {

    /**
     * Every {@link HystrixCommand} requests asks this if it is allowed to proceed or not.  It is idempotent and does
     * not modify any internal state, and takes into account the half-open logic which allows some requests through
     * after the circuit has been opened
     * 
     * @return boolean whether a request should be permitted
     */
    boolean allowRequest();

    /**
     * Whether the circuit is currently open (tripped).
     * 
     * @return boolean state of circuit breaker
     */
    boolean isOpen();

    /**
     * Invoked on successful executions from {@link HystrixCommand} as part of feedback mechanism when in a half-open state.
     */
    void markSuccess();

    /**
     * Invoked on unsuccessful executions from {@link HystrixCommand} as part of feedback mechanism when in a half-open state.
     */
    void markNonSuccess();

    /**
     * Invoked at start of command execution to attempt an execution.  This is non-idempotent - it may modify internal
     * state.
     */
    boolean attemptExecution();
}

实现子类有两个:

  • NoOpCircuitBreaker:断路器空实现
  • HystrixCircuitBreakerImpl:完整的断路器实现,在AbstractCommand构造函数中初始化HystrixCircuitBreaker(通过HystrixCircuitBreaker.Factory构造)。

HystrixCircuitBreaker 工厂

CircuitBreaker 工厂中维护了基于HystrixCommandKey的单例断路器对象实例。

private static ConcurrentHashMap circuitBreakersByCommand = new ConcurrentHashMap();

Factory代码如下:

ublic static class Factory {
        //用一个ConcurrentHashMap来保存HystrixCircuitBreaker对象
        private static ConcurrentHashMap circuitBreakersByCommand = new ConcurrentHashMap();
        
//Hystrix首先会检查ConcurrentHashMap中有没有对应的缓存的断路器,如果有的话直接返回。如果没有的话就会新创建一个HystrixCircuitBreaker实例,将其添加到缓存中并且返回
        public static HystrixCircuitBreaker getInstance(HystrixCommandKey key, HystrixCommandGroupKey group, HystrixCommandProperties properties, HystrixCommandMetrics metrics) {
            
            HystrixCircuitBreaker previouslyCached = circuitBreakersByCommand.get(key.name());
            if (previouslyCached != null) {
                return previouslyCached;
            }

            
            HystrixCircuitBreaker cbForCommand = circuitBreakersByCommand.putIfAbsent(key.name(), new HystrixCircuitBreakerImpl(key, group, properties, metrics));
            if (cbForCommand == null) {
                return circuitBreakersByCommand.get(key.name());
            } else {
                return cbForCommand;
            }
        }

        
        public static HystrixCircuitBreaker getInstance(HystrixCommandKey key) {
            return circuitBreakersByCommand.get(key.name());
        }

        static void reset() {
            circuitBreakersByCommand.clear();
        }
}

执行原理

HystrixCommand在执行的时候会与HystrixCircuitBreaker交互,执行之前会根据断路器状态来决定后续流程,执行命令成功、超时、失败又会向断路器汇报,断路器根据这些数据修改自身状态。
断路器流程图:


SpringCloud-Hystrix原理与Dubbo整合_第2张图片
image

断路器可以通过6个参数配置:

  • circuitBreaker.enabled:是否启动断路器,默认时true
  • circuitBreaker.forceOpen:是否强制打开,始终保持打开状态。
  • circuitBreaker.forceClosed:强制断路器关闭,始终保持关闭
  • circuitBreaker.errorThresholdPercentage:设定错误比例,一个时间窗口内错误请求超过给配置则断路器打开
  • circuitBreaker.requestVolumeThreshold:默认20,至少有20个请求参与errorThresholdPercentage错误百分比计算,这个参数是断路器起作用的关键
// check if we are past the statisticalWindowVolumeThreshold
if (health.getTotalRequests() < properties.circuitBreakerRequestVolumeThreshold().get()) {
    // we are not past the minimum volume threshold for the statisticalWindow so we'll return false immediately and not calculate anything
    return false;
}

if (health.getErrorPercentage() < properties.circuitBreakerErrorThresholdPercentage().get()) {
    return false;
}
  • circuitBreaker.sleepWindowInMilliseconds:半开试探时间默认值5000ms。断路器开启该配置时间后,会尝试放部分量过去,确定以来服务是否可用
  • metrics.rollingStats.timeInMilliseconds:设置滑动窗口统计时间,默认10s
  • metrics.rollingStats.numBuckets:设置滑动统计桶数量,默认10

command可以配置参数:

  • execution.isolation.strategy:执行隔离策略THREAD|SEMAPHORE;THREAD策略每次在一个线程中执行,并发请求数限制于线程池中线程数量;SEMAPHORE策略在调用线程中执行,并发请求书受限于semaphore信号量的值
  • execution.isolation.thread.timeoutInMilliseconds:请求超时时间,默认1s
  • execution.timeout.enabled:是否开启超时,默认true
  • execution.isolation.thread.interruptOnTimeout:超时情况下是否中断HystrixCommand.run()执行,默认true
  • fallback.enabled:是否开启fallback,默认true

Command 线程池配置参数

  • coreSize:设置线程池最大并发数量,默认10
  • maximumSize:设置线程池最大并发数量,默认与coreSize一致
  • maxQueueSize:最大队列长度,默认-1 SynchronizeQueue 实现
  • queueSizeRejectionThreshold:设置拒绝请求的临界值,当线程池占满+临界值占满时,请求会立即拒绝
  • keepAliveTimeMinutes:设置keep-alive时间,默认1分钟,只有当maximumSize起作用的时候才会生效,该配置控制一个线程多久没有使用后释放
  • allowMaximumSizeToDivergeFromCoreSize:确认maximumSize参数是否起作用,默认false

Dubbo 集成 Hystrix

引入hystrix到pom


    org.springframework.cloud
    spring-cloud-starter-netflix-hystrix
    1.4.4.RELEASE

Application类上增加@EnableHystrix来启用hystrix starter

@SpringBootApplication
@EnableHystrix
public class ProviderApplication {

配置Provider端

在Dubbo的Provider上增加@HystrixCommand配置,这样子调用就会经过Hystrix代理。

@Service(version = "1.0.0")
public class HelloServiceImpl implements HelloService {
    @HystrixCommand(commandProperties = {
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000") })
    @Override
    public String sayHello(String name) {
        // System.out.println("async provider received: " + name);
        // return "annotation: hello, " + name;
        throw new RuntimeException("Exception to show hystrix enabled.");
    }
}

配置Consumer端

对于Consumer端,则可以增加一层method调用,并在method上配置@HystrixCommand。当调用出错时,会走到fallbackMethod = "reliable"的调用里。

@Reference(version = "1.0.0")
private HelloService demoService;

@HystrixCommand(fallbackMethod = "reliable")
public String doSayHello(String name) {
    return demoService.sayHello(name);
}
public String reliable(String name) {
    return "hystrix fallback value";
}

你可能感兴趣的:(SpringCloud-Hystrix原理与Dubbo整合)