前期回顾:
【Zero to One系列】springcloud微服务集成nacos,形成分布式系统
【Zero to One系列】SpringCloud Gateway结合Nacos完成微服务的网关路由
1、hystrix依赖包
首先引入hystrix相关的依赖包,版本方面自己和项目内相对应即可,我这这边是直接使用的默认版本。
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
然后,演示的微服务,还是以我架构项目中的2个子模块为例,user模块与send模块:
user模块:调用方
send模块:被调用方
2、hystrix配置
2.1 feign集成hystrix熔断(统一配置)
首先,写一个send模块的feign接口fallback实现类,例如:
package com.***.common.hystrix;import com.***.common.bean.ResultBean;
import com.***.common.enums.ResponseCodeEnum;
import com.***.common.feign.SendFeignClient;
import org.springframework.stereotype.Component;@Component
public class SendFallBack implements SendFeignClient {@Overridepublic ResultBean sendSMS() {//todo 可以在对应的方法内写入使用统一降级策略,或是指定的降级策略处理return ResultBean.returnResult(ResponseCodeEnum.SUCCESS,"发送服务暂时断开连接,请稍后。。。");}
}
然后,在send模块的feign接口的注解上,直接配置对应的降级实现类,如下:
@FeignClient(name = "${sys.serviceName.send}",path = "${sys.serviceContext.send}",fallback = SendFallBack.class)
最后,在user模块中,配置上:
feign.hystrix.enabled=true
现在,启动2个微服务,我们测试一下效果:
1、显示2个服务都正常的情况下,调用结果如下:
2、通过nacos的管理界面,我们手动下线send模块服务,或是手动停止send服务,模拟服务宕机异常情况,再看下请求效果:
可以看到,通过feign集成的hystrix配置的降级处理,已经生效了。
2.2 指定接口自定义熔断配置
这里以send模块为例。。在启动类上,先加上注解:
@EnableHystrix
然后,写一个测试方法,如下:
@HystrixCommand(fallbackMethod = "failResult",commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),@HystrixProperty(name = "fallback.enabled", value = "true")})
@PostMapping(value = "/testHystrix")
public ResultBean testHystrix() throws InterruptedException {//线程睡眠2秒,模拟接口响应慢的情况Thread.sleep(2000);return ResultBean.returnResult(ResponseCodeEnum.SUCCESS,"send服务正常。。。");
}private ResultBean failResult(){return ResultBean.returnResult(ResponseCodeEnum.FAIL,"send服务暂不可用。。。");
}
启动后,我们测试一下:
可以看到,接口的执行已经进入到的降级的fallback方法中了。
这里,我贴一下HystrixCommand详细配置说明,可以参考使用:
Command属性主要用来控制HystrixCommand命令的行为,它主要分下面的类别:1、Execution:用来控制HystrixCommand.run()的执行
execution.isolation.strategy:该属性用来设置HystrixCommand.run()执行的隔离策略。默认为THREAD。
execution.isolation.thread.timeoutInMilliseconds:该属性用来配置HystrixCommand执行的超时时间,单位为毫秒。
execution.timeout.enabled:该属性用来配置HystrixCommand.run()的执行是否启用超时时间。默认为true。
execution.isolation.thread.interruptOnTimeout:该属性用来配置当HystrixCommand.run()执行超时的时候是否要它中断。
execution.isolation.thread.interruptOnCancel:该属性用来配置当HystrixCommand.run()执行取消时是否要它中断。
execution.isolation.semaphore.maxConcurrentRequests:当HystrixCommand命令的隔离策略使用信号量时,该属性用来配置信号量的大小。当最大并发请求达到该设置值时,后续的请求将被拒绝。2、Fallback:用来控制HystrixCommand.getFallback()的执行
fallback.isolation.semaphore.maxConcurrentRequests:该属性用来设置从调用线程中允许HystrixCommand.getFallback()方法执行的最大并发请求数。当达到最大并发请求时,后续的请求将会被拒绝并抛出异常。
fallback.enabled:该属性用来设置服务降级策略是否启用,默认是true。如果设置为false,当请求失败或者拒绝发生时,将不会调用HystrixCommand.getFallback()来执行服务降级逻辑。3、Circuit Breaker:用来控制HystrixCircuitBreaker的行为。
circuitBreaker.enabled:确定当服务请求命令失败时,是否使用断路器来跟踪其健康指标和熔断请求。默认为true。
circuitBreaker.requestVolumeThreshold:用来设置在滚动时间窗中,断路器熔断的最小请求数。例如,默认该值为20的时候,如果滚动时间窗(默认10秒)内仅收到19个请求,即使这19个请求都失败了,断路器也不会打开。
circuitBreaker.sleepWindowInMilliseconds:用来设置当断路器打开之后的休眠时间窗。休眠时间窗结束之后,会将断路器设置为“半开”状态,尝试熔断的请求命令,如果依然时候就将断路器继续设置为“打开”状态,如果成功,就设置为“关闭”状态。
circuitBreaker.errorThresholdPercentage:该属性用来设置断路器打开的错误百分比条件。默认值为50,表示在滚动时间窗中,在请求值超过requestVolumeThreshold阈值的前提下,如果错误请求数百分比超过50,就把断路器设置为“打开”状态,否则就设置为“关闭”状态。
circuitBreaker.forceOpen:该属性默认为false。如果该属性设置为true,断路器将强制进入“打开”状态,它会拒绝所有请求。该属性优于forceClosed属性。
circuitBreaker.forceClosed:该属性默认为false。如果该属性设置为true,断路器强制进入“关闭”状态,它会接收所有请求。如果forceOpen属性为true,该属性不生效。4、Metrics:该属性与HystrixCommand和HystrixObservableCommand执行中捕获的指标相关。
metrics.rollingStats.timeInMilliseconds:该属性用来设置滚动时间窗的长度,单位为毫秒。该时间用于断路器判断健康度时需要收集信息的持续时间。断路器在收集指标信息时会根据设置的时间窗长度拆分成多个桶来累计各度量值,每个桶记录了一段时间的采集指标。例如,当为默认值10000毫秒时,断路器默认将其分成10个桶,每个桶记录1000毫秒内的指标信息。
metrics.rollingStats.numBuckets:用来设置滚动时间窗统计指标信息时划分“桶”的数量。默认值为10。
metrics.rollingPercentile.enabled:用来设置对命令执行延迟是否使用百分位数来跟踪和计算。默认为true,如果设置为false,那么所有的概要统计都将返回-1。
metrics.rollingPercentile.timeInMilliseconds:用来设置百分位统计的滚动窗口的持续时间,单位为毫秒。
metrics.rollingPercentile.numBuckets:用来设置百分位统计滚动窗口中使用桶的数量。
metrics.rollingPercentile.bucketSize:用来设置每个“桶”中保留的最大执行数。
metrics.healthSnapshot.intervalInMilliseconds:用来设置采集影响断路器状态的健康快照的间隔等待时间。5、Request Context:涉及HystrixCommand使用HystrixRequestContext的设置。
requestCache.enabled:用来配置是否开启请求缓存。
requestLog.enabled:用来设置HystrixCommand的执行和事件是否打印到日志的HystrixRequestLog中。
3、hystrix的配置参数说明
1.HystrixCommandProperties用于HystrixCommand配置,一个HystrixCommandKey对应一个HystrixCommandProperties实例。
2.HystrixThreadPoolProperties用于HystrixThreadPool配置,一个HystrixThreadPoolKey对应一个HystrixThreadPoolProperties实例。
3.HystrixCollapserProperties用于HystrixCollapserCommand配置,一个HystrixCollapserKey对应一个HystrixCollapserProperties实例。
类别 | 配置项 | 默认值 |
HystrixCommandProperties | hystrix.threadpool.[commandkey].circuitBreaker.enabled | true |
hystrix.threadpool.[commandkey].circuitBreaker.requestVolumeThreshold | 20 | |
hystrix.threadpool.[commandkey].circuitBreaker.sleepWindowInMilliseconds | 5000 | |
hystrix.threadpool.[commandkey].circuitBreaker.errorThresholdPercentage | 50 | |
hystrix.threadpool.[commandkey].circuitBreaker.forceOpen | false | |
hystrix.threadpool.[commandkey].circuitBreaker.forceClosed | false | |
hystrix.threadpool.[commandkey].execution.isolation.strategy | Thread | |
hystrix.threadpool.[commandkey].execution.isolation.thread.timeoutInMilliseconds | 1000 | |
hystrix.threadpool.[commandkey].execution.timeout.enabled | true | |
hystrix.threadpool.[commandkey].execution.isolation.thread.interruptOnTimeout | true | |
hystrix.threadpool.[commandkey].execution.isolation.thread.interruptOnFutureCancel | false | |
hystrix.threadpool.[commandkey].execution.isolation.semaphore.maxConcurrentRequests | 10 | |
hystrix.threadpool.[commandkey].fallback.isolation.semaphore.maxConcurrentRequests | 10 | |
hystrix.threadpool.[commandkey].fallback.enabled | true | |
hystrix.threadpool.[commandkey].metrics.rollingStats.timeInMilliseconds | 10000 | |
hystrix.threadpool.[commandkey].metrics.rollingStats.numBuckets | 10 | |
hystrix.threadpool.[commandkey].metrics.rollingPercentile.enabled | true | |
hystrix.threadpool.[commandkey].metrics.rollingPercentile.timeInMilliseconds | 60000 | |
hystrix.threadpool.[commandkey].metrics.rollingPercentile.numBuckets | 6 | |
hystrix.threadpool.[commandkey].metrics.rollingPercentile.bucketSize | 100 | |
hystrix.threadpool.[commandkey].metrics.healthSnapshot.intervalInMilliseconds | 500 | |
hystrix.threadpool.[commandkey].requestCache.enabled | true | |
hystrix.threadpool.[commandkey].requestLog.enabled | true | |
hystrix.threadpool.[commandkey].threadPoolKeyOverride | ||
HystrixThreadPoolProperties | hystrix.threadpool.[threadPoolkey].coreSize | 10 |
hystrix.threadpool.[threadPoolkey].allowMaximumSizeToDivergeFromCoreSize | false | |
hystrix.threadpool.[threadPoolkey].maximumSize | 10 | |
hystrix.threadpool.[threadPoolkey].keepAliveTimeMinutes | 1 | |
hystrix.threadpool.[threadPoolkey].maxQueueSize | -1 | |
hystrix.threadpool.[threadPoolkey].queueSizeRejectionThreshold | 5 | |
hystrix.threadpool.[threadPoolkey].metrics.rollingStats.timeInMilliseconds | 10000 | |
hystrix.threadpool.[threadPoolkey].metrics.rollingStats.numBuckets | 10 | |
HystrixCollapserProperties | hystrix.collapser.[collapserCommandkey].maxRequestsInBatch | Integer.MAX_VALUE |
hystrix.collapser.[collapserCommandkey].timerDelayInMilliseconds | 10 | |
hystrix.collapser.[collapserCommandkey].requestCache.enabled | true | |
hystrix.collapser.[collapserCommandkey].metrics.rollingStats.timeInMilliseconds | 10000 | |
hystrix.collapser.[collapserCommandkey].metrics.rollingStats.numBuckets | 10 | |
hystrix.collapser.[collapserCommandkey].metrics.rollingPercentile.enabled | true | |
hystrix.collapser.[collapserCommandkey].metrics.rollingPercentile.timeInMilliseconds | 60000 | |
hystrix.collapser.[collapserCommandkey].metrics.rollingPercentile.numBuckets | 6 | |
hystrix.collapser.[collapserCommandkey].metrics.rollingPercentile.bucketSize | 100 |
内部每个属性由一个ChainHystrixProperty表示,ChainHystrixProperty是一个串联的HystrixDynamicProperty,持续获取串中的属性值,直到获得不为null值为止。ChainHystrixProperty串联的HystrixDynamicProperty默认通过插件获取的HystrixDynamicProperties获取(最后我们会讲到插件)。
HystrixDynamicProperty表示动态配置数据,如果配置源发送变化,通过该对象获取配置也会相应变化。hystrix中有种实现类:
1.通过archaius实现获取配置项,通过HystrixDynamicPropertiesArchaius创建该类HystrixDynamicProperty。
2.通过system实现获取配置项,通过HystrixDynamicPropertiesSystemProperties创建该类HystrixDynamicProperty。
还有yaml配置:
hystrix:command:#全局默认配置default:execution:timeout:#是否给方法执行设置超时时间,默认为true。一般我们不要改。enabled: trueisolation:#配置请求隔离的方式,这里是默认的线程池方式。还有一种信号量的方式semaphore,使用比较少。strategy: threadPoolsemaphore:maxConcurrentRequests: 1000thread:#方式执行的超时时间,默认为1000毫秒,在实际场景中需要根据情况设置timeoutInMilliseconds: 60000#发生超时时是否中断方法的执行,默认值为true。不要改。interruptOnTimeout: true#是否在方法执行被取消时中断方法,默认值为false。没有实际意义,默认就好!interruptOnCancel: false#熔断器相关配置##并发执行的最大线程数,默认10coreSize: 200#说明:是否允许线程池扩展到最大线程池数量,默认为false。allowMaximumSizeToDivergeFromCoreSize: true#说明:线程池中线程的最大数量,默认值是10。此配置项单独配置时并不会生效,需要启用allowMaximumSizeToDivergeFromCoreSizemaximumSize: 200#说明1:作业队列的最大值,默认值为-1。表示队列会使用SynchronousQueue,此时值为0,Hystrix不会向队列内存放作业。#说明2:如果此值设置为一个正int型,队列会使用一个固定size的LinkedBlockingQueue,此时在核心线程池都忙碌的情况下,会将作业暂时存放在此队列内,但是超出此队列的请求依然会被拒绝maxQueueSize: 20000#设置队列拒绝请求的阀值,默认为5。queueSizeRejectionThreshold: 30000circuitBreaker:#说明:是否启动熔断器,默认为true。我们使用Hystrix的目的就是为了熔断器,不要改,否则就不要引入Hystrix。enabled: true#说明1:启用熔断器功能窗口时间内的最小请求数,假设我们设置的窗口时间为10秒,#说明2:那么如果此时默认值为20的话,那么即便10秒内有19个请求都失败也不会打开熔断器。#说明3:此配置项需要根据接口的QPS进行计算,值太小会有误打开熔断器的可能,而如果值太大超出了时间窗口内的总请求数,则熔断永远也不会被触发#说明4:建议设置一般为:QPS*窗口描述*60%requestVolumeThreshold: 3000#说明1:熔断器被打开后,所有的请求都会被快速失败掉,但是何时恢复服务是一个问题。熔断器打开后,Hystrix会在经过一段时间后就放行一条请求#说明2:如果请求能够执行成功,则说明此时服务可能已经恢复了正常,那么熔断器会关闭;相反执行失败,则认为服务仍然不可用,熔断器保持打开。#说明3:所以此配置的作用是指定熔断器打开后多长时间内允许一次请求尝试执行,官方默认配置为5秒。sleepWindowInMilliseconds: 5000#说明1:该配置是指在通过滑动窗口获取到当前时间段内Hystrix方法执行失败的几率后,根据此配置来判断是否需要打开熔断器#说明2:这里官方的默认配置为50,即窗口时间内超过50%的请求失败后就会打开熔断器将后续请求快速失败掉errorThresholdPercentage: 70#说明:是否强制启用熔断器,默认false,没有什么场景需要这么配置,忽略!forceOpen: false#说明:是否强制关闭熔断器,默认false,没有什么场景需要这么配置,忽略!forceClosed: false
对于hystrix的实现原理感兴趣的,可以看下我往期的博文:
【SpringCloud微服务系列】Hystrix熔断器底层原理
至此,springcloud微服务集成hystrix熔断器的操作流程,就记录完啦。后续还会有分布式链路追踪的实现集成,感兴趣的话,请帮忙一键三连谢谢~~~