文章目录
一、Hystrix的两种使用方式
1.结合restTemplate使用
1.调用方的工程中引入hystrix依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.启动类添加注解
@EnableCircuitBreaker
注:这里使用@EnableHystrix和@EnableCircuitBreaker都是可以的,@EnableHystrix点进去包含了@EnableCircuitBreaker。
3.被调用的方法上加@HystrixCommand,该注解会将该方法放到hystrix的监控中
@HystrixCommand(fallbackMethod = "selectUserInfoFallBack")
public ResponseDto selectUserInfo(RequestDto requestDto){
//正常的代码逻辑
}
4.写对应被调用服务的降级方法,方法的入参和出参需要和被调用服务的出入参一致
public ResponseDto selectUserInfoFallBack(RequestDto requestDto){
//熔断降级后的代码逻辑
}
2.结合feign使用
1.和上面的第一步一样先加入hystrix依赖,配置文件中打开Hystrix,默认是关闭的。
feign:
hystrix:
enabled: true
2.在调用远程服务的接口上添加@FeignClient注解
@FeignClient(name = "user",fallback = FindUserInfoFallback.class)
public interface FindUserInfo{
@RequestMapping(value="/user/selectUserInfo", method = RequestMethod.POST)
public ResponseDto selectUserInfo(RequestDto requestDto);
}
@Component
public class FindUserInfoFallback implements FindUserInfo {
@Override
public ResponseDto selectUserInfo(RequestDto requestDto){
//熔断降级后的代码逻辑
}
}
3.启动类添加注解
@EnableFeignClients //开启Feign
@EnableCircuitBreaker //开启Hystrix
附:Hystrix相关的常用配置数据
HystrixCommandProperties
/* --------------统计相关------------------*/
// 统计滚动的时间窗口,默认:5000毫秒(取自circuitBreakerSleepWindowInMilliseconds)
private final HystrixProperty metricsRollingStatisticalWindowInMilliseconds;
// 统计窗口的Buckets的数量,默认:10个,每秒一个Buckets统计
private final HystrixProperty metricsRollingStatisticalWindowBuckets; // number of buckets in the statisticalWindow
// 是否开启监控统计功能,默认:true
private final HystrixProperty metricsRollingPercentileEnabled;
/* --------------熔断器相关------------------*/
// 熔断器在整个统计时间内是否开启的阀值,默认20。也就是在metricsRollingStatisticalWindowInMilliseconds(默认10s)内至少请求20次,熔断器才发挥起作用
private final HystrixProperty circuitBreakerRequestVolumeThreshold;
// 熔断时间窗口,默认:5秒.熔断器中断请求5秒后会进入半打开状态,放下一个请求进来重试,如果该请求成功就关闭熔断器,否则继续等待一个熔断时间窗口
private final HystrixProperty circuitBreakerSleepWindowInMilliseconds;
//是否启用熔断器,默认true. 启动
private final HystrixProperty circuitBreakerEnabled;
//默认:50%。当出错率超过50%后熔断器启动
private final HystrixProperty circuitBreakerErrorThresholdPercentage;
//是否强制开启熔断器阻断所有请求,默认:false,不开启。置为true时,所有请求都将被拒绝,直接到fallback
private final HystrixProperty circuitBreakerForceOpen;
//是否允许熔断器忽略错误,默认false, 不开启
private final HystrixProperty circuitBreakerForceClosed;
/* --------------信号量相关------------------*/
//使用信号量隔离时,命令调用最大的并发数,默认:10
private final HystrixProperty executionIsolationSemaphoreMaxConcurrentRequests;
//使用信号量隔离时,命令fallback(降级)调用最大的并发数,默认:10
private final HystrixProperty fallbackIsolationSemaphoreMaxConcurrentRequests;
/* --------------其他------------------*/
//使用命令调用隔离方式,默认:采用线程隔离,ExecutionIsolationStrategy.THREAD
private final HystrixProperty executionIsolationStrategy;
//使用线程隔离时,调用超时时间,默认:1秒
private final HystrixProperty executionIsolationThreadTimeoutInMilliseconds;
//线程池的key,用于决定命令在哪个线程池执行
private final HystrixProperty executionIsolationThreadPoolKeyOverride;
//是否开启fallback降级策略 默认:true
private final HystrixProperty fallbackEnabled;
// 使用线程隔离时,是否对命令执行超时的线程调用中断(Thread.interrupt())操作.默认:true
private final HystrixProperty executionIsolationThreadInterruptOnTimeout;
// 是否开启请求日志,默认:true
private final HystrixProperty requestLogEnabled;
//是否开启请求缓存,默认:true
private final HystrixProperty requestCacheEnabled;
HystrixThreadPoolProperties
/* 配置线程池大小,默认值10个 */
private final HystrixProperty corePoolSize;
/* 配置线程值等待队列长度,默认值:-1 建议值:-1表示不等待直接拒绝,测试表明线程池使用直接决绝策略+ 合适大小的非回缩线程池效率最高.所以不建议修改此值。 当使用非回缩线程池时,queueSizeRejectionThreshold,keepAliveTimeMinutes 参数无效 */
private final HystrixProperty maxQueueSize;
二、两种捕获熔断异常信息
1.结合restTemplate使用时
修改熔断降级的方法,添加Throwable即可
public ResponseDto selectUserInfoFallBack(RequestDto requestDto,Throwable throwable){
log.info("异常信息:"+throwable);
//熔断降级后的代码逻辑
}
2.集合feign使用时
1.修改调用远程服务接口上的@FeignClient注解
@FeignClient(name = "user",fallback = FindUserInfoFallbackFactory.class)
2.新建对应的Factory类(匿名内部类,入参出参需要一致)
@Component
public class FindUserInfoFallbackFactory implements FallbackFactory<FindUserInfo> {
@Override
public FindUserInfo create(Throwable cause) {
return new FindUserInfo() {
@Override
public ResponseDto selectUserInfo(RequestDto requestDto){
log.info("feign异常信息:"+cause);
//熔断降级后的代码逻辑
}
};
}
}
三、断路器开关
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
可以访问http://ip:端口/actuator/health
默认断路器打开条件10秒内请求超过20次且失败率超过50%
附:相关属性配置
Execution相关的属性的配置:
hystrix.command.default.execution.isolation.strategy 隔离策略,默认是Thread, 可选Thread|Semaphore
thread 通过线程数量来限制并发请求数,可以提供额外的保护,但有一定的延迟。一般用于网络调用
semaphore 通过semaphore count来限制并发请求数,适用于无网络的高并发请求
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令执行超时时间,默认1000ms
hystrix.command.default.execution.timeout.enabled 执行是否启用超时,默认启用true
hystrix.command.default.execution.isolation.thread.interruptOnTimeout 发生超时是是否中断,默认true
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。
semaphore应该占整个容器(tomcat)的线程池的一小部分。
Fallback相关的属性
这些参数可以应用于Hystrix的THREAD和SEMAPHORE策略
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests 如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。默认10
hystrix.command.default.fallback.enabled 当执行失败或者请求被拒绝,是否会尝试调用hystrixCommand.getFallback() 。默认true
Circuit Breaker相关的属性
hystrix.command.default.circuitBreaker.enabled 用来跟踪circuit的健康性,如果未达标则让request短路。默认true
hystrix.command.default.circuitBreaker.requestVolumeThreshold 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求,即使19个请求都失败,也不会触发circuit break。默认20
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒绝request,也就是5000毫秒后才会关闭circuit。默认5000
hystrix.command.default.circuitBreaker.errorThresholdPercentage错误比率阀值,如果错误率>=该值,circuit会被打开,并短路所有请求触发fallback。默认50,即为50%。
hystrix.command.default.circuitBreaker.forceOpen 强制打开熔断器,如果打开这个开关,那么拒绝所有request,默认false
hystrix.command.default.circuitBreaker.forceClosed 强制关闭熔断器 如果这个开关打开,circuit将一直关闭且忽略circuitBreaker.errorThresholdPercentage
Metrics相关参数
hystrix.command.default.metrics.rollingStats.timeInMilliseconds 设置统计的时间窗口值的,毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000
hystrix.command.default.metrics.rollingStats.numBuckets 设置一个rolling window被划分的数量,若numBuckets=10,rolling window=10000,那么一个bucket的时间即1秒。必须符合rolling window % numberBuckets == 0。默认10
hystrix.command.default.metrics.rollingPercentile.enabled 执行时是否enable指标的计算和跟踪,默认true
hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds 设置rolling percentile window的时间,默认60000
hystrix.command.default.metrics.rollingPercentile.numBuckets 设置rolling percentile window的numberBuckets。逻辑同上。默认6
hystrix.command.default.metrics.rollingPercentile.bucketSize 如果bucket size=100,window=10s,若这10s里有500次执行,只有最后100次执行会被统计到bucket里去。增加该值会增加内存开销以及排序的开销。默认100
hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds 记录health 快照(用来统计成功和错误绿)的间隔,默认500ms
data = pd.read_csv(
'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())
四、监控
监控
调用方引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
访问页面http://ip:端口/actuator/hystrix.stream发现一直在通过ping进行监控
五、原理
1.隔离策略
使用舱壁模式的优点:1.服务提供者的异常不会影响整个系统的瘫痪。2.利用独立的线程池可以控制每个调用者的并发度
两种隔离策略:
THREAD(线程隔离):使用该方式,HystrixCommand将会在单独的线程上执行,并发请求受线程池中线程数量的限制。不同服务通过使用不同线程池,彼此间将不受影响,达到隔离效果。hystrix将使用独立的线程池对应每一个服务提供者,用于隔离和限制这些服务。于是某个服务提供者的高延迟或者资源受限只会发生在该服务提供者对应的线程池中。
SEMAPHORE(信号量隔离):其实就是个计数器,使用该方式,HystrixCommand将会在调用线程上执行,通过信号量限制单个服务提供者的并发量,开销相对较小(因为不用那么多线程池),并发请求受到信号量个数的限制。 线程隔离会带来线程开销,有些场景(比如无网络请求场景)可能会因为用开销换隔离得不偿失,为此hystrix提供了信号量隔离,当服务的并发数大于信号量阈值时将进入fallback。
Hystrix中默认并且推荐使用线程隔离(THREAD), 一般来说,只有当调用负载异常高时(例如每个实例每秒调用数百次)才需要信号量隔离,因为这种场景下使用THREAD开销会比较高。信号量隔离一般仅适用于非网络调用的隔离。
线程池和信号量都支持熔断和限流。相比线程池,信号量不需要线程切换,因此避免了不必要的开销。但是信号量不支持异步,也不支持超时,也就是说当所请求的服务不可用时,信号量会控制超过限制的请求立即返回,但是已经持有信号量的线程只能等待服务响应或从超时中返回,即可能出现长时间等待。线程池模式下,当超过指定时间未响应的服务,Hystrix会通过响应中断的方式通知线程立即结束并返回。
2.Hystrix实现思路
1.请求过来时,将请求的远程调用逻辑,封装到HystrixCommand或者HystrixObservableCommand对象(并在构造方法配置请求被执行需要的参数)中,这些远程调用将会在独立的线程中执行。(资源隔离、命令模式)。
2.Hystrix对访问耗时超过设置阈值的请求采用自动超时的策略。该策略对所有的命令都有效。(如果是信号量隔离方式,则此特性失效),超时的阈值可以通过命令配置进行自定义。
3.为每个服务提供者维护一个线程池(信号量),当线程池(信号量)被占满时,对于该服务提供者的请求将会被直接拒绝(快速失败,走回滚)而不是排队等待,减少系统等待资源。
4.针对请求服务提供者划分出成功、失效、超时和线程池被占满等情况。
5.断路器将在请求服务提供者失败次数超过一定阈值后手动或自动切断服务一段时间。
6.当请求服务提供者出现服务拒绝、超时和 短路(多个服务提供者依次顺序请求,前面的服务提供者请求失败,后面的请求将不再发出)等情况,执行器fallback方法,服务降级。
7.提供近乎实时的监控和配置变更服务。
3.Hystrix实现流程
1. 构建HystrixCommand或者HystrixObservableCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数。
2. 执行命令,Hystrix提供了4种执行命令的方法。
3. 检查是否有相同命令执行的缓存,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动。
4. 检查断路器是否打开,如果打开走 第8步。
5. 检查线程池或者信号量是否被消耗完,如果已满,走第8步。
6. 调用HystrixCommand的run 或者 HystrixObservableCommand的construct 执行被封装的调用逻辑,如果执行失败或超时,走第8步。
7. 计算链路的健康情况
8. 在命令执行失败时获取fallback逻辑。
9. 返回响应。