SpringCloud-Hystrix的使用

  • Hystrix的基本使用
  • Hystrix的属性

基本使用

例子为:HystrixCommand命令对象的同步执行方式.

配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@Configuration
@EnableHystrix //开启Hystrix功能
public class HystrixConfig {
public static final String API_COMMAND_KEY = "apiCommandKey";
public static final String API_THREADPOOL_KEY = "apiThreadpoolKey";
public static final String API_COMMAND_GROUPKEY = "apiCommandGroupKey";

@Value("${api.thread.timeoutInSeconds:1}")
private Long apiTimeoutInSeconds;
@Value("${api.circuitBreaker.requestVolumeThreshold:100}")
private Long apiCircuitBreakThreshold;
@Value("${api.circuitBreaker.sleepWindowInSeconds:5}")
private Long apiCiruitBreakSleepWindowInSeconds;

@Bean
public AbstractConfiguration configurationManager(){
AbstractConfiguration configurationManager = ConfigurationManager.getConfigInstance();
// 命令的配置
// 命令执行策略 默认 使用线程池方式
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".execution.isolation.strategy", HystrixCommandProperties.ExecutionIsolationStrategy.THREAD);
// 命令超时设置 单位为毫秒 默认
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".execution.isolation.thread.timeoutInMilliseconds", apiTimeoutInSeconds * 1000);
// 开启命令超时 默认
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".execution.timeout.enabled", true);
// 命令超时后被中断 默认
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".execution.isolation.thread.interruptOnTimeout", true);
// 熔断开启 默认
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".circuitBreaker.enabled",true);
// 熔断临界值 一个滚动窗口(比如10s)请求失败数达到临界值则熔断标志打开 默认100
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".circuitBreaker.requestVolumeThreshold", apiCircuitBreakThreshold);
// 跳闸后的多长时间可再次确认电路是否闭合 默认5000
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".circuitBreaker.sleepWindowInMilliseconds", apiCiruitBreakSleepWindowInSeconds * 1000);
// 错误比例(熔断需要请求错误比例以及错误数到达临界值) 默认
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".circuitBreaker.errorThresholdPercentage", 50);
// 滚动窗口持续时间 (默认10s)
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".metrics.rollingStats.timeInMilliseconds", 10000);
// 滚动统计窗口分成的桶数 滚动窗口持续时间%桶数 == 0 默认
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".metrics.rollingStats.numBuckets", 10);
// 桶的大小 桶数*大小/滚动窗口>每秒请求数
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".metrics.rollingPercentile.bucketSize", 500);
// 请求缓存功能
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".requestCache.enabled", false);
// 请求日志功能
configurationManager.setProperty("hystrix.command." + API_COMMAND_KEY + ".requestLog.enabled",false);

// 线程池的配置
// 核心线程数:在健康时每秒的请求高峰数 × 99%的延迟秒数+一些喘息的空间时 默认
configurationManager.setProperty("hystrix.threadpool." + API_THREADPOOL_KEY + ".coreSize", 10);
// 最大线程数 默认
configurationManager.setProperty("hystrix.threadpool." + API_THREADPOOL_KEY + ".maximumSize", 10);
// 队列实现以及大小 -1-SynchronousQueue 其他正值-LinkedBlockingQueue
configurationManager.setProperty("hystrix.threadpool." + API_THREADPOOL_KEY + ".maxQueueSize",100);
// 队列大小拒绝临界值,可小于队列大小
configurationManager.setProperty("hystrix.threadpool." + API_THREADPOOL_KEY + ".queueSizeRejectionThreshold",100);
// 非核心线程在释放前的空闲时间 默认
configurationManager.setProperty("hystrix.threadpool." + API_THREADPOOL_KEY + ".keepAliveTimeMinutes", 1);
// 允许核心线程数和最大线程数值不同
configurationManager.setProperty("hystrix.threadpool." + API_THREADPOOL_KEY + ".allowMaximumSizeToDivergeFromCoreSize", true);
return configurationManager;
}
}

业务逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@HystrixCommand(fallbackMethod = "homeworkInfoFallback",
commandKey = HystrixConfig.API_COMMAND_KEY,
threadPoolKey = HystrixConfig.API_THREADPOOL_KEY,
groupKey = HystrixConfig.API_COMMAND_GROUPKEY,
ignoreExceptions = {ErrorCodeException.class}
)
public List<HomeworkInfoItem> homeworkInfo(List<Long> homeworkIds) {
if (CollectionsUtil.isNullOrEmpty(homeworkIds)) {
return Collections.emptyList();
}
HomeworksInfoResponse response = HttpManagerUtil.post(homeworkUrl, homeworkIds, HomeworksInfoResponse.class);
return response.getHomeworkInfoListList();
}

// 降级逻辑
public List<HomeworkInfoItem> homeworkInfoFallback(List<Long> homeworkIds, Throwable e) {
logger.warn("execute homeworkInfoFallback,homeworkIds:{}, ex:{}", homeworkIds, e.getMessage());
return Collections.emptyList();
}

创建命令

使用@HystrixCommand注解, 注解标注的地方就是命令的内容, 方法返回值为业务对象时,是通过同步执行, 如果方法返回值为Futrue<业务对象>, 并且return new AsyncResult<业务对象>{实现invoke()}时, 是通过异步执行的.

定义降级

@HystrixCommand 有个参数 fallbackMethod 可以配置fallback逻辑, 配置一个方法名字符串, 并且当前类中定义一个方法与之对应. 当命令无法执行时就会降级到这个方法去处理, 注意降级方法的参数和返回值需要与命令方法对应.

异常处理

HystrixCommand实现的run()方法抛出异常时, 除了HystrixBadRequestException以外, 都会被Hystrix认为是执行失败, 并触发降级逻辑, 如果不想处理某些异常, 可以配置参数 ignoreExceptions, 比如例子中的ErrorCodeException, 将会不被Hystrix处理, 而是向外抛出.

降级方法中的参数最后一个传入Throwable可以在降级方法中获得异常相关信息.

命令分组与资源划分

参数groupKey,commandKey,threadPoolKey 分别表示分组名, 命令名, 线程池名. 可以通过这些名称, 批量的设置一些属性以灵活的使用Hystrix.

请求的缓存与合并

请求缓存: 第一次命令的结果缓存起来, 第二次相同的命令直接从缓存中取, 不用再执行具体的命令
请求合并: 命令执行前经过一个合并处理器, 合并很短的时间窗口内的对同一个服务的多次请求, 多个请求变成单个批量请求, 以减少资源的占用.

没用过, 就先略了, 以后用到了再写.

属性配置

属性存在于下面4个不同优先级别的配置(由低到高)

  1. 全局默认
  2. 全局配置
  3. 实例默认值
  4. 实例默认属性

全局的配置可以使用AbstractConfiguration来配置. 如上述例子, 实例配置使用@HystrixCommand注解的commandProperties参数, 例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@HystrixCommand(
commandProperties = {
@HystrixProperty(name = "XXX1", value = "yyy1"),
@HystrixProperty(name = "XXX2", value = "yyy2"),
},
threadPoolProperties = {
@HystrixProperty(name = "XXX1", value = "yyy1"),
@HystrixProperty(name = "XXX2", value = "yyy2"),
})
@HystrixCollapser(batchMethod = "ZZZ", collapserProperties = {
@HystrixProperty(name = "XXX1", value = "yyy1"),
@HystrixProperty(name = "XXX2", value = "yyy2"),
})
public List<HomeworkInfoItem> homeworkInfo(List<Long> homeworkIds) {
// 略
}

Command属性

包含5个不同类型的属性配置:

  • {HystrixCommandKey},{HystrixCollapserKey},{HystrixThreadPoolKey}"default"时为全局配置属性

execution配置

execution配置控制了HystrixCommand.run()执行.

| 配置名 | 默认 | 配置 |
|—–|——|——–|——-|——–|—-|
| execution.isolation.strategy | THREAD | hystrix.command.{HystrixCommandKey}.execution.isolation.strategy |
| execution.isolation.thread.timeoutInMilliseconds | 1000 | hystrix.command.{HystrixCommandKey}.execution.isolation.thread.timeoutInMilliseconds |
| execution.timeout.enabled | true | hystrix.command.{HystrixCommandKey}.execution.timeout.enabled |
| execution.isolation.thread.interruptOnTimeout | true | hystrix.command.{HystrixCommandKey}.execution.isolation.thread.interruptOnTimeout |
| execution.isolation.thread.interruptOnCancel | false | hystrix.command.{HystrixCommandKey}.execution.isolation.thread.interruptOnCancel |
| execution.isolation.semaphore.maxConcurrentRequests | 10 | hystrix.command.{HystrixCommandKey}.execution.isolation.semaphore.maxConcurrentRequests |

分别用来设置:

  • HystrixCommand.run()执行的隔离策略, 有两个选项 THREAD, SEMAPHORE.
  • HystrixCommand执行的超时时间, 单位毫秒. 当执行超过这个时间, Hystrix将会进入降级逻辑.
  • 设置HystrixCommand.run()的执行是否启用超时时间, 默认为true. 配置为false, 会导致上一个的配置无效.
  • 用来配置HystrixCommand.run()超时时是否要将其中断.
  • 用来配置HystrixCommand.run()执行被取消时是否要将其中断.
  • 隔离策略为 SEMAPHORE时, 用这个配置信号量大小, 最大并发达到这个时, 后续请求会被拒绝.

fallback配置

fallback配置控制HystrixCommand.getFallback()执行.

| 配置名 | 默认 | 配置 |
|—–|——|——–|——-|——–|—-|
| fallback.isolation.semaphore.maxConcurrentRequests | 10 | hystrix.command.{HystrixCommandKey}.fallback.isolation.semaphore.maxConcurrentRequests |
| fallback.enabled | true | hystrix.command.{HystrixCommandKey}.fallback.enabled |

分别用来设置:

  • 设置从调用线程中允许进入HystrixCommand.getFallback()方法执行的最大并发请求数. 若超过了, 后续请求会直接被拒绝并抛出异常.
  • 设置服务降级是否启用, 默认true. 如果为false, 请求失败或拒绝时不会进入降级逻辑.

circuitBreaker配置

circuitBreaker配置控制HystrixCircuitBreaker的行为.

| 配置名 | 默认 | 配置 |
|—–|——|——–|——-|——–|—-|
| circuitBreaker.enabled | true | hystrix.command.{HystrixCommandKey}.circuitBreaker.enabled |
| circuitBreaker.requestVolumeThreshold | 20 | hystrix.command.{HystrixCommandKey}.circuitBreaker.requestVolumeThreshold |
| circuitBreaker.sleepWindowInMilliseconds | 5000 | hystrix.command.{HystrixCommandKey}.circuitBreaker.sleepWindowInMilliseconds |
| circuitBreaker.errorThresholdPercentage | 50 | hystrix.command.{HystrixCommandKey}.circuitBreaker.errorThresholdPercentage |
| circuitBreaker.forceOpen | false | hystrix.command.{HystrixCommandKey}.circuitBreaker.forceOpen |
| circuitBreaker.forceClosed | false | hystrix.command.{HystrixCommandKey}.circuitBreaker.forceClosed |

分别用来设置:

  • 当服务请求失败时, 是否使用断路器来跟踪健康度和熔断请求. 如果为false, 请求失败后后续的请求依然会走正常逻辑.
  • 设置滚动时间窗口内, 断路器熔断的最小请求数. 即:一个时间段内, 失败次数超过了这个值才会熔断(有可能熔断,还有其他条件呦).
  • 设置断路器打开后的休眠时间窗. 休眠时间窗结束后, 进入半开状态, 将会尝试执行一个命令, 如果失败了断路器打开, 如果成功了断路器关闭.
  • 设置断路器打开的错误百分比条件, 时间窗口内, 请求数超过阈值的前提下, 错误比例超过这个配置设置的值时, 才会打开断路器, 否则关闭.
  • 强制打开断路器. 优先级大于circuitBreaker.forceClosed. 用于服务异常时, 人为修改以拒绝服务.
  • 强制关闭断路器. 如果circuitBreaker.forceOpen为true, 这个没效. 用于强制设置不断路.

metrics配置

metrics配置与HystrixCommandHystrixObservableCommand执行中捕获的指标信息有关.

| 配置名 | 默认 | 配置 |
|—–|——|——–|——-|——–|—-|
| metrics.rollingStats.timeInMilliseconds | 10000 | hystrix.command.{HystrixCommandKey}.metrics.rollingStats.timeInMilliseconds |
| metrics.rollingStats.numBuckets | 10 | hystrix.command.{HystrixCommandKey}.metrics.rollingStats.numBuckets |
| metrics.rollingPercentile.enabled | true | hystrix.command.{HystrixCommandKey}.metrics.rollingPercentile.enabled |
| metrics.rollingPercentile.timeInMilliseconds | 60000 | hystrix.command.{HystrixCommandKey}.metrics.rollingPercentile.timeInMilliseconds |
| metrics.rollingPercentile.numBuckets | 6 | hystrix.command.{HystrixCommandKey}.metrics.rollingPercentile.numBuckets |
| metrics.rollingPercentile.bucketSize | 100 | hystrix.command.{HystrixCommandKey}.metrics.rollingPercentile.bucketSize |
| metrics.healthSnapshot.intervalInMilliseconds | 500 | hystrix.command.{HystrixCommandKey}.metrics.healthSnapshot.intervalInMilliseconds |

分别用来设置:

  • 滚动时间窗口的长度, 单位毫秒, 需要能被metrics.rollingStats.numBuckets整除, 否则启动抛异常, 且无法使用动态参数.
  • 滚动时间窗口统计的指标信息划分的桶的数量.对metrics.rollingStats.timeInMilliseconds的划分. 控制健康指标的存储粒度. 且无法使用动态参数.
  • 设置命令执行的延迟是否使用百分位来跟踪和计算. 如果为false, 所有概率统计都返回-1.
  • 设置百分位统计的滚动时间窗口的持续时间, 单位毫秒. 需要能被metrics.rollingPercentile.numBuckets整除. 且无法使用动态参数.
  • 设置百分位统计滚动窗口中使用的桶的数量. 对metrics.rollingPercentile.timeInMilliseconds的划分.
  • 设置执行过程中每个桶中保留的最大执行次数. 例如: 设置为100, 滚动窗口10秒, 如果10秒内一个桶发生了500次执行, 那么这个桶中保留最后100次执行的统计. 另外增加该值大小会增加内存量的消耗, 并增加排序百分位数所需的计算时间. 且无法使用动态参数.
  • 设置采集影响断路器状态的健康快照(请求的成败比)的间隔等待时间.

requestContext配置

requestContext配置涉及到HystrixCommand使用的HystrixRequestContext的配置.

| 配置名 | 默认 | 配置 |
|—–|——|——–|——-|——–|—-|
| requestCache.enabled | true | hystrix.command.{HystrixCommandKey}.requestCache.enabled |
| requestLog.enabled | true | hystrix.command.{HystrixCommandKey}.requestLog.enabled |

分别用来设置:

  • 是否开启请求缓存.
  • HystrixCommand的执行和事件是否打印日志到HystrixRequestLog中.

collapse属性

| 配置名 | 默认 | 配置 |
|—–|——|——–|——-|——–|—-|
| maxRequestsInBatch | Integer.MAX_VALUE | hystrix.collapser.{HystrixCollapserKey}.maxRequestsInBatch |
| timerDelayInMilliseconds | 10 | hystrix.collapser.{HystrixCollapserKey}.timerDelayInMilliseconds |
| requestCache.enabled | true | hystrix.collapser.{HystrixCollapserKey}.requestCache.enabled |

分别用来设置:

  • 设置一次请求合并批处理中允许的最大请求数.
  • 设置批处理过程中每个命令延迟的时间, 单位毫秒.
  • 设置批处理过程中是否开始请求缓存.

threadPool配置

| 配置名 | 默认 | 配置 |
|—–|——|——–|——-|——–|—-|
| coreSize | 10 | hystrix.threadpool.{HystrixThreadPoolKey}.coreSize |
| maximumSize | 10 | hystrix.threadpool.{HystrixThreadPoolKey}.maximumSize |
| maxQueueSize | -1 | hystrix.threadpool.{HystrixThreadPoolKey}.maxQueueSize |
| queueSizeRejectionThreshold | 5 | hystrix.threadpool.{HystrixThreadPoolKey}.queueSizeRejectionThreshold |
| keepAliveTimeMinutes | 1 | hystrix.threadpool.{HystrixThreadPoolKey}.keepAliveTimeMinutes |
| allowMaximumSizeToDivergeFromCoreSize | false | hystrix.threadpool.{HystrixThreadPoolKey}.allowMaximumSizeToDivergeFromCoreSize |
| metrics.rollingStats.timeInMilliseconds | 10000 | hystrix.threadpool.{HystrixThreadPoolKey}.metrics.rollingStats.timeInMilliseconds |
| metrics.rollingStats.numBuckets | 10 | hystrix.threadpool.{HystrixThreadPoolKey}.metrics.rollingStats.numBuckets |

分别用来设置:

  • 执行命令线程池核心线程数(命令执行最大并发量).
  • 最大容量大小
  • 线程池的最大队列大小. 如果为-1, 使用SynchronousQueue实现, 否则使用LinkedBlockingQueue. 且无法使用动态参数.
  • 为队列设置拒绝阈值, 超过这个的将被拒绝. LinkedBlockingQueue队列不能动态修改其对象的大小, 这个配置可以动态改, 不用LinkedBlockingQueue时这配置无效.
  • 保活时间, 单位分钟.
  • 允许最大大小偏离核心大小
  • 滚动时间窗口的长度, 单位毫秒, 需要能被metrics.rollingStats.numBuckets整除, 否则启动抛异常, 且无法使用动态参数.(注意与metrics设置的区别)
  • 滚动时间窗口统计的指标信息划分的桶的数量.对metrics.rollingStats.timeInMilliseconds的划分. 控制健康指标的存储粒度. 且无法使用动态参数.(注意与metrics设置的区别)