导读


今天和大家聊一聊在Spring Cloud微服务框架实践中,比较核心但是又很容易把人搞得稀里糊涂的一个问题,那就是在Spring Cloud中Hystrix、Ribbon以及Feign它们三者之间在处理微服务调用超时从而触发熔断降级的关系是什么?

我们知道在Spring Cloud微服务体系下,微服务之间的互相调用可以通过Feign进行声明式调用,在这个服务调用过程中Feign会通过Ribbon从服务注册中心获取目标微服务的服务器地址列表,之后在网络请求的过程中Ribbon就会将请求以负载均衡的方式打到微服务的不同实例上,从而实现Spring Cloud微服务架构中最为关键的功能即服务发现及客户端负载均衡调用。

另一方面微服务在互相调用的过程中,为了防止某个微服务的故障消耗掉整个系统所有微服务的连接资源,所以在实施微服务调用的过程中我们会要求在调用方实施针对被调用微服务的熔断逻辑。而要实现这个逻辑场景在Spring Cloud微服务框架下我们是通过Hystrix这个框架来实现的。

调用方会针对被调用微服务设置调用超时时间,一旦超时就会进入熔断逻辑,而这个故障指标信息也会返回给Hystrix组件,Hystrix组件会根据熔断情况判断被调微服务的故障情况从而打开熔断器,之后所有针对该微服务的请求就会直接进入熔断逻辑,直到被调微服务故障恢复,Hystrix断路器关闭为止。

Hystrix、Feign及Ribbon的配置说明


接下来我们先来看看在Spring Cloud微服务系统中Hystrix、Feign及Ribbon的常用配置都有哪些以及它们的使用场景分别是什么?

Hystrix配置说明

在Spring Cloud微服务体系中Hystrix主要被用于实现实现微服务之间网络调用故障的熔断、过载保护及资源隔离等功能。而要正确使用Hystrix提供的这些功能就需要对Hystrix常用的配置有一定深入的了解,否则你会发现使用过程中认为一定会生效的配置常常不会起作用,接下来我们就按照参数配置的类型对Hystrix中的常见配置做一个梳理。

1)、线程隔离相关配置

Hystrix具备的重要关键特性之一就是它能够实现对第三方服务依赖的资源隔离,而隔离最常见的方式是通过线程池资源的隔离来实现的,Hystrix会为每个第三方服务依赖配置单独的线程池资源,从而避免对第三方服务依赖的请求占用应用主线程资源以免造成系统雪崩。Hystrix中关于线程隔离相关的配置如下:

hystrix:
command:
#全局默认配置
default:
#线程隔离相关
execution:
timeout:
#是否给方法执行设置超时时间,默认为true。一般我们不要改。
enabled: true
isolation:
#配置请求隔离的方式,这里是默认的线程池方式。还有一种信号量的方式semaphore,使用比较少。
strategy: threadPool
thread:
#方式执行的超时时间,默认为1000毫秒,在实际场景中需要根据情况设置
timeoutInMilliseconds: 1000
#发生超时时是否中断方法的执行,默认值为true。不要改。
interruptOnTimeout: true
#是否在方法执行被取消时中断方法,默认值为false。没有实际意义,默认就好!
interruptOnCancel: false

  

2)、熔断器相关配置

熔断器是Hystrix最主要的功能,它开启和关闭的时机、灵敏度及准确性是Hystrix是否能够发挥重要的关键,而在Hystrix中与熔断器相关的几个配置如下:

hystrix:
command:
#全局默认配置
default:
#熔断器相关配置
circuitBreaker:
#说明:是否启动熔断器,默认为true。我们使用Hystrix的目的就是为了熔断器,不要改,否则就不要引入Hystrix。
enabled: true
#说明1:启用熔断器功能窗口时间内的最小请求数,假设我们设置的窗口时间为10秒,
#说明2:那么如果此时默认值为20的话,那么即便10秒内有19个请求都失败也不会打开熔断器。
#说明3:此配置项需要根据接口的QPS进行计算,值太小会有误打开熔断器的可能,而如果值太大超出了时间窗口内的总请求数,则熔断永远也不会被触发
#说明4:建议设置一般为:QPS*窗口描述*60%
requestVolumeThreshold: 20
#说明1:熔断器被打开后,所有的请求都会被快速失败掉,但是何时恢复服务是一个问题。熔断器打开后,Hystrix会在经过一段时间后就放行一条请求
#说明2:如果请求能够执行成功,则说明此时服务可能已经恢复了正常,那么熔断器会关闭;相反执行失败,则认为服务仍然不可用,熔断器保持打开。
#说明3:所以此配置的作用是指定熔断器打开后多长时间内允许一次请求尝试执行,官方默认配置为5秒。
sleepWindowInMilliseconds: 5000
#说明1:该配置是指在通过滑动窗口获取到当前时间段内Hystrix方法执行失败的几率后,根据此配置来判断是否需要打开熔断器
#说明2:这里官方的默认配置为50,即窗口时间内超过50%的请求失败后就会打开熔断器将后续请求快速失败掉
errorThresholdPercentage: 50
#说明:是否强制启用熔断器,默认false,没有什么场景需要这么配置,忽略!
forceOpen: false
#说明:是否强制关闭熔断器,默认false,没有什么场景需要这么配置,忽略!
forceClosed: false

  

3)、Metrics(统计器)相关配置

 

Hystrix是否正常工作最主要的依赖就是根据捕获的调用指标信息来判断是否打开或者关闭熔断器,而影响Hystrix行为很重要的因素就是以下Hystrix关于Metrics的配置。

hystrix:
command:
#全局默认配置
default:
metrics:
rollingStats:
#说明:此配置用于设置Hystrix统计滑动窗口的时间,单位为毫秒,默认设置为10000毫秒,即一个滑动窗口默认统计的是10秒内的请求数据。
timeInMilliseconds: 10000
#说明2:此属性指定了滑动统计窗口划分的桶数。默认为10。
#说明2:需要注意的是,metrics.rollingStats.timeInMilliseconds % metrics.rollingStats.numBuckets == 0必须成立,否则就会抛出异常
numBuckets: 10 rollingPercentile:
#说明1:此属性配置统计方法是否响应时间百分比,默认为true。
#说明2:Hystrix会统计方法执行1%,10%,50%,90%,99%等比例请求的平均耗时用来生成统计图表。
#说明3:如果禁用该参数设置false,那么所有汇总统计信息(平均值、百分位数)将返回-1。
enabled: true
#说明:统计响应时间百分比时的窗口大小,默认为60000毫秒,即1分钟
timeInMilliseconds: 60000
#说明1:此属性用于设置滑动百分比窗口要划分的桶数,默认为6。
#说明2:需要注意的是,metrics.rollingPercentile.timeInMilliseconds % metrics.rollingPercentile.numBuckets == 0必须成立,否则会抛出异常
numBuckets: 6
#说明1:该属性表示统计响应时间百分比,每个滑动窗口的桶内要保存的请求数,默认为100。
#说明2:即默认10秒的桶内,如果执行了500次请求,那么只有最后100次请求执行的信息会被保存到桶内。
#说明3:增加这个值会增加内存消耗量,一般情况下无需更改。
bucketSize: 100 healthSnapshot:
#说明1:该参数配置了健康数据统计器(会影响Hystrix熔断)中每个桶的大小,默认为500毫秒。
#说明2:在统计时Hystrix通过metrics.rollingStats.timeInMilliseconds / metrics.healthSnapshot.intervalInMilliseconds计算出桶数。
#说明3:在窗口滑动时,每滑过一个桶的时间就统计一次当前窗口内请求的失败率。
intervalInMilliseconds: 500

  

在上述关于Metrics的配置中出现了两个比较频繁的概念:滑动窗口、桶,Hystrix的统计器就是由滑动窗口来实现的。关于滑动窗口举一个非常形象的例子,假设你坐在一辆大巴车的上,车窗外是一排排笔直的大树,车辆在高速地行驶着,大树迅速地从车窗滑过,如果用每棵树来代表一个网络请求,用大巴车的行驶代表时间的流逝。那么大巴车的窗口就是一个非常典型的滑动窗口,而你通过这个车窗能够看到的大树就是Hystrix要统计的数据。

桶(bucket)是Hystrix统计滑动窗口数据时的最小单位。同样以上面的例子为例,在大巴车行驶非常快的情况下,如果每掠过一棵树就统计一次窗口内大树的数据的话,会造成比较大的开销,而如果我们将车窗分成10份,大巴车行驶时每掠过窗口的1/10就统计一次数据,那么开销就会小很多了。所以,Hystrix中的桶就是滑动窗口1/N的概念

4)、线程池相关配置

在前面提到过Hystrix实现对第三方服务依赖资源隔离最主要的方式就是通过线程池,而Hystrix内线程的使用是基于Java内置线程池的简单封装,通过以下Hystrix线程池参数我们可以控制执行Hystrix命令的线程池的行为。具体如下:

hystrix:
command:
default:
#说明:核心线程池的大小,默认值是10
coreSize: 10
#说明:是否允许线程池扩展到最大线程池数量,默认为false。
allowMaximumSizeToDivergeFromCoreSize: false
#说明:线程池中线程的最大数量,默认值是10。此配置项单独配置时并不会生效,需要启用allowMaximumSizeToDivergeFromCoreSize
maximumSize: 10
#说明1:作业队列的最大值,默认值为-1。表示队列会使用SynchronousQueue,此时值为0,Hystrix不会向队列内存放作业。
#说明2:如果此值设置为一个正int型,队列会使用一个固定size的LinkedBlockingQueue,此时在核心线程池都忙碌的情况下,会将作业暂时存放在此队列内,但是超出此队列的请求依然会被拒绝
maxQueueSize: -1
#设置队列拒绝请求的阀值,默认为5。
queueSizeRejectionThreshold: 5
#控制线程在释放前未使用的时间,默认为1分钟。
keepAliveTimeMinutes: 1

  

Ribbon配置说明

Ribbon在Spring Cloud中对于支持微服之间的通信发挥着非常关键的作用,其主要功能包括客户端负载均衡器及用于中间层通信的客户端。在基于Feign的微服务通信中无论是否开启Hystrix,Ribbon都是必不可少的,Ribbon的配置参数主要如下:

ribbon:
#说明:同一台实例的最大自动重试次数,默认为1次,不包括首次
MaxAutoRetries: 1
#说明:要重试的下一个实例的最大数量,默认为1,不包括第一次被调用的实例
MaxAutoRetriesNextServer: 1
#说明:是否所有的操作都重试,默认为true
OkToRetryOnAllOperations: true
#说明:从注册中心刷新服务器列表信息的时间间隔,默认为2000毫秒,即2秒
ServerListRefreshInterval: 2000
#说明:使用Apache HttpClient连接超时时间,单位为毫秒
ConnectTimeout: 3000
#说明:使用Apache HttpClient读取的超时时间,单位为毫秒
ReadTimeout: 3000
#说明:初始服务器列表,不需要手工配置,在运行时动态根据注册中心更新
listOfServers: www.microsoft.com:80,www.yahoo.com:80,www.google.com:80

  

以上配置方式将对所有的微服务调用有效,如果想针对单独的微服务进行配置,使用“微服务名.ribbon”这样的配置方式即可,例如:

bike:
ribbon:
ReadTimeout: 30000
operation:
ribbon:
ReadTimeout: 30000

  

Feign配置说明

 

Feign是一款Java语言编写的HttpClient绑定器,在Spring Cloud微服务中用于实现微服务之间的声明式调用,Feign自身可以支持多种HttpClient工具包,例如OkHttp及Apache HttpClient,针对不同的HttpClient其默认常见配置如下:

feign:
hystrix:
enabled: true
client:
config:
#JDK默认HttpURLConnection 实现的 Http Client配置
default:
#连接超时时间
connectTimeout: 5000
#读取超时时间
readTimeout: 5000
#错误解码器
errorDecoder: com.wudimanong.client.common.FeignClientErrorDecoder
#解码器
encoder: com.wudimanong.client.common.FeignClientEncoder
#编码器
decoder: com.wudimanong.client.common.FeignClientDecoder

  

Feign、Hystrix、Ribbon的超时配置关系


在前面的内容我们分别单独梳理了Feign、Hystrix及Ribbon三者常见的配置,针对各自的特性功能配置我们并没有异议,但是我们也看到它们都有针对微服务超时的配置,而在开启熔断器功能后,这些超时配置会影响到熔断器及服务降级逻辑的行为,那么它们之间超时的配置有什么关系呢?如下:

如上图所示,在Spring Cloud中使用Feign进行微服务调用分为两层:Ribbon的调用及Hystrix的调用。所以Feign的超时时间就是Ribbon和Hystrix超时时间的结合,而如果不启用Hystrix则Ribbon的超时时间就是Feign的超时时间配置,Feign自身的配置会被覆盖。

而如果开启了Hystrix,那么Ribbon的超时时间配置与Hystrix的超时时间配置则存在依赖关系,因为涉及到Ribbon的重试机制,所以一般情况下都是Ribbon的超时时间小于Hystrix的超时时间,否则会出现以下错误:

2019-07-12 11:10:20,238 397194 [http-nio-8084-exec-2] WARN  o.s.c.n.z.f.r.s.AbstractRibbonCommand - The Hystrix timeout of 40000ms for the command operation is set lower than the combination of the Ribbon read and connect timeout, 80000ms.

那么Ribbon和Hystrix的超时时间配置的关系具体是什么呢?如下:

Hystrix的超时时间=Ribbon的重试次数(包含首次)*(ribbon.ReadTimeout+ribbon.ConnectTimeout)

而Ribbon的重试次数的计算方式为:

Ribbon重试次数(包含首次)=1+ribbon.MaxAutoRetries+ribbon.MaxAutoRetriesNextServer+(ribbon.MaxAutoRetries*ribbon.MaxAutoRetriesNextServer)

以上图中的Ribbon配置为例子,Ribbon的重试次数=1+(1+1+1)*(30000+10000),所以Hystrix的超时配置应该>=160000毫秒。在Ribbon超时但Hystrix没有超时的情况下,Ribbon便会采取重试机制;而重试期间如果时间超过了Hystrix的超时配置则会立即被熔断(fallback)

如果不配置Ribbon的重试次数,则Ribbon默认会重试一次,加上第一次调用Ribbon的重试次数为2次,以上述配置为例Hystrix超时时间配置为2*40000=80000,由于很多情况下,大家一般不会主动配置Ribbon的重试次数,所以这里需要注意下!强调下,以上超时配置的值只是示范,超时配置有点大不太合适实际的线上场景,大家根据实际情况设置即可!

PS:以上整理应该是全网最全的一份,如果觉得有用辛苦转发下,给在使用Spring Cloud微服务的朋友们送去一点小温暖!^_^

「微信搜索公众号-》无敌码农」 获取更多Spring Cloud微服务技能!

Spring Cloud中Hystrix、Ribbon及Feign的熔断关系是什么?的更多相关文章

  1. Spring Cloud中,如何解决Feign/Ribbon第一次请求失败的问题?

    Spring Cloud中,如何解决Feign/Ribbon第一次请求失败的问题? Spring Cloud中,Feign和Ribbon在整合了Hystrix后,可能会出现首次调用失败的问题,要如何解 ...

  2. Spring Cloud中,如何解决Feign整合Hystrix第一次请求失败的问题

    Spring Cloud中,Feign和Ribbon在整合了Hystrix后,可能会出现首次调用失败的问题,要如何解决该问题呢? 造成该问题的原因 Hystrix默认的超时时间是1秒,如果超过这个时间 ...

  3. Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失问题分析

    最近spring boot项目中由于使用了spring cloud 的hystrix 导致了threadLocal中数据丢失,其实具体也没有使用hystrix,但是显示的把他打开了,导致了此问题. 导 ...

  4. 详解Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失

    在Spring Cloud中我们用Hystrix来实现断路器,Zuul中默认是用信号量(Hystrix默认是线程)来进行隔离的,我们可以通过配置使用线程方式隔离. 在使用线程隔离的时候,有个问题是必须 ...

  5. spring cloud 的hystrix 熔断器 和feign 调用的使用

    1, 添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId&g ...

  6. Spring Cloud 之 Hystrix 知识点:隔离、熔断、降级

    Hystrix 是隔离.熔断以及降级的一个框架. Hystrix 的隔离: Hystrix 会搞很多个小小的线程池,比如订单服务请求库存服务是一个线程池,请求仓储服务是一个线程池,请求积分服务是一个线 ...

  7. Spring Cloud(Dalston.SR5)--Ribbon 中间层负载均衡

    Spring Cloud 集成了 Ribbon 并结合 Eureka 可以实现客户端的负载均衡,使用 @LoadBalanced 修饰的 RestTemplate 类拥有了负载均衡功能,在 Sprin ...

  8. spring Cloud中,解决Feign/Ribbon整合Hystrix第一次请求失败的问题?

    Spring Cloud中,Feign和Ribbon在整合了Hystrix后,可能会出现首次调用失败的问题,要如何解决该问题呢? 造成该问题的原因 Hystrix默认的超时时间是1秒,如果超过这个时间 ...

  9. Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul)

    Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul) 1.Eureka Eureka是Netflix的一个子模块,也是核心模块之一.Eureka是 ...

随机推荐

  1. ext中设置grid单选,取消选择

    原代码(无法取消选择)如下: selModel: Ext.create('Ext.selection.CheckboxModel', { mode: "SINGLE", allow ...

  2. new和delete必须成对出现吗?【网上集合贴+个人总结】

    new和delete必须成对出现吗?[网上集合贴+个人总结] 1.从内存泄露与否的角度考虑 new 和 delete不一定要成对出現.理论上是這樣的.但是从习惯上來說,new delete成對出現是一 ...

  3. OpenCv的python环境搭建

    1.python的安装参看 http://www.cnblogs.com/samo/p/6734403.html 2.OpenCv安装.opencv2.4.10可以支持vc10/vc11/vc12,o ...

  4. Md2All:好用的markdown文件转换工具,文章迁移微信公众号的利器

    目录 简介 使用体验 极速上手 更多功能 总结 简介 markdown以简单的语法和强大的功能,征服了无数技术创作者,几乎主流的技术博客网站都开始支持markdown语言撰写博客.但是微信公众号的文章 ...

  5. shell多线程之进程间通信

    # 这是一个简单的并发程序,有如下要求: # .有两个程序a和b,希望他们能并发执行,以节约时间 # .a和b都是按照日期顺序执行,但b每日程序的前提条件是当日a的程序已经执行完毕 #解决方案: # ...

  6. AWR报告分析案例及命令(收集)

    AWR报告分析案例(收集) 循序渐进解读Oracle AWR性能分析报告 AWR报告分析之一:高 DB CPU 消耗的性能根源 生成AWR报告命令: 1)连接数据库:sqlplus / as sysd ...

  7. Storm —— 集群环境搭建

    一.集群规划 这里搭建一个3节点的Storm集群:三台主机上均部署Supervisor和LogViewer服务.同时为了保证高可用,除了在hadoop001上部署主Nimbus服务外,还在hadoop ...

  8. spring 5.x 系列第7篇 —— 整合Redis客户端 Jedis和Redisson (xml配置方式)

    文章目录 一.说明 1.1 Redis 客户端说明 1.2 Redis可视化软件 1.3 项目结构说明 1.3 依赖说明 二.spring 整合 jedis 2.1 新建基本配置文件 2.2 单机配置 ...

  9. Idea中maven项目中导入本地jar包

    说一下正确的流程: 1.将jar包导入到本地maven库或者远程nexus仓库,再使用maven引用: 2.导入命令: //通过一下信息引入maven -DgroupId=com.test -Dart ...

  10. 【转载】JDK自带的log工具

    版权声明:本文为Jaiky_杰哥原创,转载请注明出处.This blog is written by Jaiky, reproduced please indicate. https://blog.c ...