Hystrix-开源容错系统(下)

简介: Hystrix-开源容错系统(下)


4.5 降级回退方式


降级的常用处理方式,返回默认值,返回缓存里的值(包括本地缓存,远程redis缓存),但是回退的处理方式有不适合的场景。如写操作、批处理、计算等等。以上几种情况如果失败,则程序就要将错误返回给调用者。


Fail Fast快速失败


如果我们实现的是HystrixObservableCommand.java则 重写 resumeWithFallback方法。


image.png


Fail Silent 无声失败


返回null,空Map,空List。如图。重写getFallback()方法。

image.png

Fallback: Static 返回默认值


回退的时候返回静态嵌入代码中的默认值,这样就不会导致功能以Fail Silent的方式被清楚,也就是用户看不到任何功能了。而是按照一个默认的方式显示。


Fallback: Stubbed 自己组装一个值返回


在Fallback方法中组装初始化好的值。


Fallback: Cache via Network 利用远程缓存


通过远程缓存的方式,在失败的情况下再次发起一次remote请求缓存数据。由于是又发起一起远程调用,所以会重新封装一次Command,这个时候要注意,执行fallback的线程一定要跟主线程区分开,也就是重新命名一个ThreadPoolKey。


Primary + Secondary with Fallback 主次方式回退(主要和次要)


这种方式类似于我们上线一个新的功能,但为了防止新功能上线失败可以回退到老的代码,我们会做一个开关比如使用zookeeper做一个配置开关,可以动态切换到老代码功能。Hystrix使用通过一个配置来在两个command中进行切换。

image.png

代码如下:usePrimary可以通过ucc来配置。

image.png


4.6 隔离策略


执行依赖代码的线程与请求线程(比如Tomcat线程)分离,请求线程可以自由控制离开的时间,这也是我们通常说的异步编程,Hystrix是结合RxJava来实现的异步编程。通过设置线程池大小来控制并发访问量,当线程饱和的时候可以拒绝服务,防止依赖问题扩散。


4.6.1 线程隔离


优缺点


  1. 应用程序会被完全保护起来,即时依赖的一个服务线程池满了,也不会影响到应用程序的其他部分。
  2. 当依赖的服务恢复时,应用程序能恢复到正常的性能。
  3. 当参数配置错误时,线程池的状态会很快显示出来,比如延迟、超时、拒绝等。同时可以通过动态属性实时执行来处理纠正错误的参数配置。
  4. 如果服务的性能有变化,从而需要调整,比如增加或者减少超时时间,更改重试次数,就可以通过线程池指标动态属性修改,并不会影响到其他调用请求。注意:尽管线程池提供了隔离,但是我们的客户端底层代码也必须得有超时设置,不能无限制的阻塞以致线程池一直饱和。
  5. 线程池的主要缺点就是它增加了计算的开销,每个业务请求(被包装成命令)在执行的时候,会涉及到请求排队,调度和上下文切换。不过Netflix公司内部认为线程隔离开销足够小,不会产生重大的成本或性能的影响。



性能花费


Netflix API每天使用线程隔离的方式处理10亿多的Hystrix Command任务,每个API实例都有40多个线程池,每个线程池都有5-20个线程(大多数设置为10)

下图显示了一个HystrixCommand在单个API实例上每秒执行60个请求(每个服务器每秒执行大约350个线程执行总数)。从图上可知:


在中间偏下位置,用单一线程是没有性能消耗的。


TP90的消耗大概是单一线程为3ms。


单一线程TP99大概是有9ms的消耗。但是增长的性能花费远小于单一线程增长的执行时间(网络请求),线程执行时间从2-28ms然而花费从0-9ms。


对大多数Netflix使用的案例,这样TP90或者更高的电路响应时间(花销)是可以接受的,这样换取了系统的韧性。


image.png


4.6.2 信号量隔离


对于不依赖网络访问的服务,比如只依赖内存缓存这种情况下,就不适合用线程池隔离技术,而是采用信号量隔离。


信号量隔离只是限制了总的并发数,服务使用主线程进行同步调用,即没有线程池。因此,某个服务的如果只是想限制总并发调用量或者调用的服务不涉及远程调用的话,可以使用轻量级的信号量来实现。


image.png


4.6.3 隔离策略对比


这张图说明了线程池隔离和信号量隔离的主要区别:线程池方式下业务请求线程和执行依赖的服务的线程不是同一个线程;信号量方式下业务请求线程和执行依赖服务的线程是同一个线程。

image.png

下表对比了线程池和信号量主要的特点异同。信号量和线程池隔离方式都支持熔断和限流。

image.png

信号量隔离图解。

image.png

线程池隔离图解。

image.png


4.7 Collapsing


使用场景:HystrixCollapser用于对多个相同业务的请求合并到一个线程甚至可以合并到一个连接中执行,降低线程交互次和IO数,但必须保证他们属于同一依赖。


  • 产生原因?无论是SOA架构还是微服务架构的系统,往往会通过RPC方式或者HTTP请求方式依赖外部的接口。而远程调用过程中最常见的问题就是通信消耗与连接数占用。在高并发情况下,因通信次数的增加,调用方在本地线程池缓存的请求数、被调用方的性能消耗和网络通信次数都会导致总的通信时间变得不那么理想。为了优化这些问题,Hystrix提供了HystrixCollapser来实现请求的合并,以减少网络通信消耗和本地线程的占用。
  • HystrixCollapser实现了在HystrixCommand之前放置一个合并处理器,它会在一个很短的时间内(通过timerDelayInMilliseconds参数设置,默认是10毫秒)内对同一依赖服务的多个请求进行整理合并以批量方式发起请求(服务端需提供批量的接口)。通过HystrixCollaper的封装,开发者不需要去关注线程合并和请求结果分发的细节,只需关注批量化服务。如下图,没有Collapsing时,请求数=线程数=网络连接数。当使用Collapsing,将每个提交的请求合并到Collapser,通过1个线程完成数据的获取,所以,窗口中的请求数=1个线程=1个网络连接。
    image.png
  • 请求合并的使用场景
    在选择是否使用Collapers时,主要考虑下面两个方面。
    (1)请求命令本身的延迟。如果依赖服务的请求命令本身是一个高延迟的命令,则可以使用请求合并器,因为延迟时间窗的时间消耗就显得微不足道了。
    (2)延迟时间窗内的并发量。如果时间窗内只有很小的并发,这样反而会导致系统瓶颈,因为每个请求需要多消耗一个时间窗才响应。如果一个时间窗内有很高的并发,并且服务方也实现了批量处理接口,那么Collapser可以有效减小网络连接数和提升系统吞吐量。此时延迟时间窗所增加的消耗就忽略不计了。


对于Collapser,个人建议慎用。除非你能准确评估两者的利弊。


5. 实例


5.1 Hello World


image.png

image.png

5.2 SpringMVC-注解方式


image.png


步骤1:获取切入点方法;

步骤2:根据方法的注解HystrixCommand或者HystrixCollapser生成相应的CommandMetaHolderFactory或者CollapserMetaHolderFactory类。

步骤3:将原方法的属性set进metaHolder中;

步骤4:根据metaHolder生成相应的HystrixCommand,包含加载hystrix配置信息。commandProperties加载的优先级为前缀hystrix.command.commandKey > hystrix.command.default > defaultValue(原代码默认);threadPool配置加载的优先级为 前缀hystrix.threadpool.groupKey.> hystrix.threadpool.default.> defaultValue(原代码默认)。

步骤5:执行命令。


倘若需要给该方法指定groupKey和commandKey定义其fallback方法,则可通过添加注解属性来实现。


5.2.1 Command Properties


Execution


包括

execution.isolation.strategy、

execution.isolation.thread.timeoutInMilliseconds、

execution.timeout.enabled、

execution.isolation.thread.interruptOnTimeout、

execution.isolation.thread.interruptOnCancel、

execution.isolation.semaphore.maxConcurrentRequests。


Fallback


包括

fallback.isolation.semaphore.maxConcurrentRequests、

fallback.enabled。


Circuit Breaker


包括

circuitBreaker.enabled、

circuitBreaker.requestVolumeThreshold、

circuitBreaker.sleepWindowInMilliseconds、

circuitBreaker.errorThresholdPercentage、

circuitBreaker.forceOpen、

circuitBreaker.forceClosed。


Metrics


包括

metrics.rollingStats.timeInMilliseconds、

metrics.rollingStats.numBuckets、

metrics.rollingPercentile.enabled、

metrics.rollingPercentile.timeInMilliseconds、

metrics.rollingPercentile.numBuckets、

metrics.rollingPercentile.bucketSize、

metrics.healthSnapshot.intervalInMilliseconds。


Request Context


包括

requestCache.enabled、

requestLog.enabled。


5.2.2 Collapser Properties


包括

maxRequestsInBatch、

timerDelayInMilliseconds、

requestCache.enabled。


5.2.3 Thread Pool Properties


包括coreSize、maximumSize、maxQueueSize、queueSizeRejectionThreshold、keepAliveTimeMinutes、allowMaximumSizeToDivergeFromCoreSize、metrics.rollingStats.timeInMilliseconds、metrics.rollingStats.numBuckets。


5.3 功能总结


5.3.1 Core function


  • Isolate


Maintain a small thread pool for each dependency.  

                 -- avoid cascading failures into whole system.

                 -- rapidly recover

                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("HelloWorldPool"))


  • Latent control


NOT available when choose SEMAPHORE isolation

                .withExecutionTimeoutInMilliseconds(3000)))


  • Fail fast


a. If pool is full, be immediately rejected instead of queued up;

                b. Circuit breaker (https://github.com/Netflix/Hystrix/wiki/How-it-Works#circuit-breaker)


Fallback and degrade gracefully implements getFallback() method


5.3.2 Extension function


  • Request Collapsing
  • Request Caching
  • Near real-time monitoring, alerting, and operational control


6. 网关引入和实现思路


6.1 接入姿势


姿势很重要!从Controller引入还是从RPC层引入?如果从Controller引入,Controller对应的方法由一个线程去通过RPC方式获取所有的资源。如果是从RPC层引入,则每个RPC方法对应一个线程池,这样可以灵活控制每个RPC接口的访问情况。网关接口使用这种方式引入。


6.2 实现思路


image.png

参数设置依据


Thread Size = peak healthy × 99th percentile latency in seconds + some breathing room(线程池大小 = 峰值QPS * 99耗时 + 预留空间 )


超时设定标准


With retry,Time = 99th mean-time + 50th mean-time

Without Retry,Time = 99.5meantime


7. 总结


本文主要从hystrix原理和实现两个方面对hystrix进行讲解。其中对原理的实现上可能会有没有考虑到的问题,因公司内部已有监控的服务,对hystrix监控没有进行讲解,其他有疑问之处,欢迎拍砖。


8. 参考


降级回退方式

https://www.jianshu.com/p/b6e8d91b2a96?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

各种注解属性http://zyouwei.com/%E6%8A%80%E6%9C%AF%E7%AC%94%E8%AE%B0/Java/Hystrix-configuration.html

请求合并

https://www.jianshu.com/p/ddaa71462b26

hystrix-翻译比较好的文章

http://youdang.github.io/2016/02/05/translate-hystrix-wiki-how-it-works/

http://www.cnblogs.com/java-synchronized/p/7927726.html

https://www.jianshu.com/p/73a07e06a9d5?from=timeline

https://www.jianshu.com/p/6c574abe50c1?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

http://blog.csdn.net/qq_17751605/article/details/51225976

http://blog.csdn.net/xiaojia1100/article/details/65631778


相关文章
|
开发框架 负载均衡 Java
Spring Cloud 介绍及负载均衡Ribbon、服务容错Hystrix 组件使用详解
Spring Cloud 介绍及负载均衡Ribbon、服务容错Hystrix 组件使用详解
208 0
|
2月前
|
Java 对象存储 开发者
故障隔离与容错处理:Hystrix在Spring Cloud和Netflix OSS中的应用
故障隔离与容错处理:Hystrix在Spring Cloud和Netflix OSS中的应用
53 3
|
5月前
|
监控 Java UED
Java一分钟之-Spring Cloud Netflix Hystrix:容错管理
【6月更文挑战第9天】Spring Cloud Hystrix是用于微服务容错管理的库,通过断路器模式防止服务雪崩。本文介绍了Hystrix的基本概念,如断路器、线程隔离和fallback机制,并展示了如何快速上手,包括添加依赖、启用注解和编写Hystrix命令。此外,还讨论了常见问题(如断路器打开、资源泄漏和不当的Fallback策略)及其解决方案。通过自定义Hystrix指标监控,可以进一步优化系统性能。理解Hystrix工作原理并适时调整配置,对于构建健壮的微服务至关重要。
200 3
|
6月前
|
监控 数据可视化 Java
Spring Cloud Hystrix:服务容错保护
Spring Cloud Hystrix:服务容错保护
213 0
|
6月前
|
监控 数据可视化 Java
【使用Hystrix实现服务容错和熔断】—— 每天一点小知识
【使用Hystrix实现服务容错和熔断】—— 每天一点小知识
|
监控 负载均衡 Java
Spring Cloud【Finchley】-08使用Hystrix实现容错
Spring Cloud【Finchley】-08使用Hystrix实现容错
133 0
|
运维 监控 数据可视化
Hystrix Dashboard 让你更了解系统的运行情况
断路器的打开和关闭状态的变化是由系统收集一些重要参数,当达到条件时才触发的。而这些请求情况的指标信息都是 HystrixCommand和 HystrixObservableCommand实例在执行过程中记录的重要信息,为了帮助我们系统运维或性能优化做出判断, HystrixDashboard实现Hystrix指标数据的可视化。 接口实现使用了 @HystrixCommand注解后,这个接口的调用情况会被Hystrix记录下来,并用来给断路器和 HystrixDashboard使用。 Hystrix-dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboa
|
缓存 运维 监控
SpringCloud-Hystrix——让你的系统稳一点儿
在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与订阅的方式互相依赖。由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因等待出现故障的依赖方响应而形成任务积压,线程资源无法释放,最终导致自身服务的瘫痪,进一步甚至出现故障的蔓延最终导致整个系统的瘫痪,导致服务雪崩效应。为了解决这样的问题,产生了断路器等一系列的服务保护机制。
|
缓存 监控 Java
从零学SpringCloud系列(四):服务容错保护Hystrix
从零学SpringCloud系列(四):服务容错保护Hystrix
154 0
从零学SpringCloud系列(四):服务容错保护Hystrix
|
缓存 监控 Dubbo
服务容错&Hystrix|学习笔记
快速学习服务容错&Hystrix
服务容错&Hystrix|学习笔记