vlambda博客
学习文章列表

微服务中Hystrix的作用详解

前言

本文在书写过程中,参考了大量文档,如《Spring Cloud与Docker微服务架构实战》周立著、红帽Openshift官方技术文档、Openshift社区相关文档。本文在书写过程中,也引用了互联网的一些概念描述,文章最后会列出参考文献链接。



什么是Hystrix

笔者在之前文章《从一个实验看微服务架构---不谈理念讲干货》中,简单介绍了基于Openshift实现微服务的方法。在实验中,所有微服务都通过容器来实现:

在《从一个实验看微服务架构---不谈理念讲干货》文章中,笔者提到了Hystrix作为熔断器的存在,但介绍不是很深,本次我们详细看一下。

微服务中Hystrix的作用详解

首先,Hystrix是Netflix公司开源的一个项目。那么Netflix公司是做什么的呢?这是一个有意思的话题。Netflix(Nasdaq NFLX) 成立于1997年,是一家在线影片租赁提供商,主要提供Netflix超大数量的DVD并免费递送,总部位于美国加利福尼亚州洛斯盖图。可能很多人不知道Netflix,但有个很有名的美剧-纸牌屋,其每集片头都会显示Netflix:

微服务中Hystrix的作用详解


所以说,开源社区需要全社会的参与。

实际上,netflix和K8S有个集成的项目,叫Kubeflix。也就是说netflix把它的一些开源方案直接与K8S在社区里集成。Kubeflix主要有四个方案:Hystrix、Turbine、Ribbon、API网关。


Hystrix默认只能显示一个服务的治理信息,turbine是可以帮助把很多个服务和服务实例的信息进行聚合,hystrix dashboard里面的信息才是整体的。如下图显示,hystrix dashboard会读取turbine收集的数据:

微服务中Hystrix的作用详解

Ribbon 是 Netflix 发布的云中间层服务开源项目,其主要功能是提供客户侧软件负载均衡算法,将 Netflix 的中间层服务连接在一起。



Hystrix详解

有个词,叫“雪崩效应”,相信很多人都听过。它其实是从“雪球越滚越大”的现象抽象出来的。在单体应用中,多个业务的功能模块放在一个应用中(如三层架构的网银),功能模块之前是紧耦合,单体应用要么整体稳定运行,要么整体出现问题,整体不可用。

微服务中Hystrix的作用详解

按照上图,Ola是Hola的基础服务、Hola是Aloha的基础服务、Aloha是Bonjpur的基础服务。那么,如果Ola微服务出现问题,不可调用,那显然会影响到Hola的调用、Aloha调用、Bonjpur的调用。这就像雪球一样,越滚越大,越到后面,影响越严重。


要想避免雪崩现象,就需要有容器机制,采用断路模式。为每个微服务前面加一个“保险丝”。当电流过大的时候(如服务访问超时,并且超过设定的重试次数),保险丝烧断,中断客户端对该应用的访问,而访问其他好的应用。


微服务常见实现容错的工具是Hystrix。Hystrix实现容错主要有以下两点:

1. 设置网络超时

网络超时指的是,当对一个微服务的远程调用,如果响应太慢,那远程调用对应的这个线程/进程就得不到释放,如果数量比较多,最终大量消耗系统资源。因此就需要为每个网络请求设置超时时间。


2.使用断路器

断路器指的是,当对摸一个微服务的请求有大量超时的时候,以让这个微服务对外通讯中断,实现快速失败。这就像家里的保险丝一样。


同时,断路器可以对已经被断路的微服务进行检测,查看微服务是否已经恢复正常,是的话,就恢复该应用对外提供服务。就像下面这样(示意图)

微服务中Hystrix的作用详解

正常情况下,A、B、C三个微服务的断路器都是关闭的。


1.如果一段时间内,对A微服务的访问失败率或错误率达到一定阈值;断路器打开,对A微服务的请求全部被中断。

2.断路器打开一段时间后,断路器允许一个请求访问微服务A,检测是否调用成功,如果成功,则关闭断路器,失败,则断路器保持打开的状态。


Hytrix参数设置(引用http://blog.csdn.net/caomiao2006/article/details/50000511):

1):Command 配置

Command配置源码在HystrixCommandProperties,构造Command时通过Setter进行配置

具体配置解释和默认值如下

  1. //使用命令调用隔离方式,默认:采用线程隔离,ExecutionIsolationStrategy.THREAD  

  2. private final HystrixProperty<ExecutionIsolationStrategy> executionIsolationStrategy;   

  3. //使用线程隔离时,调用超时时间,默认:1秒  

  4. private final HystrixProperty<Integer> executionIsolationThreadTimeoutInMilliseconds;   

  5. //线程池的key,用于决定命令在哪个线程池执行  

  6. private final HystrixProperty<String> executionIsolationThreadPoolKeyOverride;   

  7. //使用信号量隔离时,命令调用最大的并发数,默认:10  

  8. private final HystrixProperty<Integer> executionIsolationSemaphoreMaxConcurrentRequests;  

  9. //使用信号量隔离时,命令fallback(降级)调用最大的并发数,默认:10  

  10. private final HystrixProperty<Integer> fallbackIsolationSemaphoreMaxConcurrentRequests;   

  11. //是否开启fallback降级策略 默认:true   

  12. private final HystrixProperty<Boolean> fallbackEnabled;   

  13. // 使用线程隔离时,是否对命令执行超时的线程调用中断(Thread.interrupt())操作.默认:true  

  14. private final HystrixProperty<Boolean> executionIsolationThreadInterruptOnTimeout;   

  15. // 统计滚动的时间窗口,默认:5000毫秒circuitBreakerSleepWindowInMilliseconds  

  16. private final HystrixProperty<Integer> metricsRollingStatisticalWindowInMilliseconds;  

  17. // 统计窗口的Buckets的数量,默认:10个,每秒一个Buckets统计  

  18. private final HystrixProperty<Integer> metricsRollingStatisticalWindowBuckets; // number of buckets in the statisticalWindow  

  19. //是否开启监控统计功能,默认:true  

  20. private final HystrixProperty<Boolean> metricsRollingPercentileEnabled;   

  21. // 是否开启请求日志,默认:true  

  22. private final HystrixProperty<Boolean> requestLogEnabled;   

  23. //是否开启请求缓存,默认:true  

  24. private final HystrixProperty<Boolean> requestCacheEnabled; // Whether request caching is enabled. 

2)熔断器(Circuit Breaker)配置

Circuit Breaker配置源码在HystrixCommandProperties,构造Command时通过Setter进行配置,每种依赖使用一个Circuit Breaker

  1. // 熔断器在整个统计时间内是否开启的阀值,默认20秒。也就是10秒钟内至少请求20次,熔断器才发挥起作用  

  2. private final HystrixProperty<Integer> circuitBreakerRequestVolumeThreshold;   

  3. //熔断器默认工作时间,默认:5秒.熔断器中断请求5秒后会进入半打开状态,放部分流量过去重试  

  4. private final HystrixProperty<Integer> circuitBreakerSleepWindowInMilliseconds;   

  5. //是否启用熔断器,默认true. 启动  

  6. private final HystrixProperty<Boolean> circuitBreakerEnabled;   

  7. //默认:50%。当出错率超过50%后熔断器启动.  

  8. private final HystrixProperty<Integer> circuitBreakerErrorThresholdPercentage;  

  9. //是否强制开启熔断器阻断所有请求,默认:false,不开启  

  10. private final HystrixProperty<Boolean> circuitBreakerForceOpen;   

  11. //是否允许熔断器忽略错误,默认false, 不开启  

  12. private final HystrixProperty<Boolean> circuitBreakerForceClosed;  



3):命令合并(Collapser)配置

Command配置源码在HystrixCollapserProperties,构造Collapser时通过Setter进行配置

  1. //请求合并是允许的最大请求数,默认: Integer.MAX_VALUE  

  2. private final HystrixProperty<Integer> maxRequestsInBatch;  

  3. //批处理过程中每个命令延迟的时间,默认:10毫秒  

  4. private final HystrixProperty<Integer> timerDelayInMilliseconds;  

  5. //批处理过程中是否开启请求缓存,默认:开启  

  6. private final HystrixProperty<Boolean> requestCacheEnabled;  



4):线程池(ThreadPool)配置

  1. /** 

  2. 配置线程池大小,默认值10个. 

  3. 建议值:请求高峰时99.5%的平均响应时间 + 向上预留一些即可 

  4. */  

  5. HystrixThreadPoolProperties.Setter().withCoreSize(int value)  

  6. /** 

  7. 配置线程值等待队列长度,默认值:-1 

  8. 建议值:-1表示不等待直接拒绝,测试表明线程池使用直接决绝策略+ 合适大小的非回缩线程池效率最高.所以不建议修改此值。 

  9. 当使用非回缩线程池时,queueSizeRejectionThreshold,keepAliveTimeMinutes 参数无效 

  10. */  

  11. HystrixThreadPoolProperties.Setter().withMaxQueueSize(int value)  


Hytrix界面展示

在笔者是实验环境中,Hystrix-dashboard是一个容器, turbine也是个容器:


微服务中Hystrix的作用详解

微服务中Hystrix的作用详解

点击Monitor Stream,进入主界面:

微服务中Hystrix的作用详解

在监控界面中,具体的指标描述,参照下图,其中Circut代表断路器的状态,下图是关闭的状态:

微服务中Hystrix的作用详解


我们查看实验环境中,一个微服务的状态.hola service:

微服务中Hystrix的作用详解

将这个微服务对应的容器和rc删掉,先进行查看:

微服务中Hystrix的作用详解

删除rc,dc和pod

微服务中Hystrix的作用详解

微服务中Hystrix的作用详解

查看Hytrix,近10s的访问失败率是100%,此时熔断器还是关闭状态:

微服务中Hystrix的作用详解

在过一小会(1分钟左右),熔断器打开,处于open状态:

重建dc后,pod和service重建后,过一会holo的状态恢复正常,断路器关闭:


参考文献:

  1. http://blog.csdn.net/caomiao2006/article/details/50000511

  2. https://github.com/Netflix/Hystrix