原理探究

1、Hystrix 的设计宗旨

  • 为第三方系统访问(通常是指通过网络) 中发送的延时和错误(例如:服务数据库异常)提供保护和控制.
  • 终止复杂分布式系统中的级联故障 .
  • 快速失败(熔断)和快速恢复.
  • 回退(fallback) 并且在可能的情况下进行服务降级.
  • 启用近乎实时的监视,警报和操作控制.

2、Hystrix 的设计原则(工作原理)

  • 防止单个依赖服务耗尽整个容器(例如:tomcat,jboss等)用户线程
  • 减少负载并快速失败,而不是排队(之间断路,而不是等待恢复)。
  • 在允许的情况下提供备用机制,保护用户免受故障影响。
  • 使用隔离技术 (例如隔离, 泳道, 断路) 去限制一个依赖服务故障带来的影响
  • 通过近实时指标,监视和警报优化发现时间
  • 通过在Hystrix的大多数方面中以低延迟传播配置更改来优化恢复时间,并支持动态属性更改,这使您可以通过低延迟反馈环路进行实时操作修改。
  • 防止整个服务集群执行失败,而不仅仅是网络请求的失败(网络阻塞)。

3、Hystrix 如何实现设计原则

  • 将依赖服务(或者是依赖项)包装在一个单独线程执行的 HystrixCommand 或 HystrixObservableCommand 对象中执行(命令模式)。
  • 请求超时花费的时间超过定义的阈值(配置的超时时间)。Hystrix提供一个超时配置,这个配置比实际的请求时间要略高一些,这些请求若发生超时,会直接拒绝请求(这里也是返回超时异常的主要原因)。
  • Hystrix 会维护一个小的线程池(或者信号量);如果信号量或者线程池已满,请求会直接被拒绝而不是等待或排队。
  • 计算成功或失败 (通过Hystrix客户端抛出的异常), 超时, 和线程拒绝.
  • 如果某个服务的发生错误的百分比超过阈值,则会触发断路器断路(跳闸)。在接线来的一段时间里会自动或者手动的停止特定请求(被执行断路的请求)。
  • 对发生请求失败,请求拒绝,请求超时,或断路的请求执行 回退(Fallback)策略。
  • 实时的监控和动态配置。

4、Hystrix流程图

Hystrix原理及熔断降级理解 - 图1

5、Hystrix整个工作流如下

  1. 构造一个 HystrixCommand或HystrixObservableCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数;
  2. 执行命令,Hystrix提供了4种执行命令的方法,后面详述;
  3. 判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动;
  4. 判断熔断器是否打开,如果打开,跳到第8步;
  5. 判断线程池/队列/信号量是否已满,已满则跳到第8步;
  6. 执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,跳到第8步;否则,跳到第9步;
  7. 统计熔断器监控指标;
  8. 走Fallback备用逻辑
  9. 返回请求响应

6、执行命令的几种方法

Hystrix提供了4种执行命令的方法,execute()和queue() 适用于HystrixCommand对象,而
observe()和toObservable()适用于HystrixObservableCommand对象。

1、execute()

以同步堵塞方式执行run(),只支持接收一个值对象。hystrix会从线程池中取一个线程来
执行run(),并等待返回值。

2、queue()

以异步非阻塞方式执行run(),只支持接收一个值对象。调用queue()就直接返回一个
Future对象。可通过Future.get()拿到run()的返回结果,但Future.get()是阻塞执行的。
若执行成功,Future.get()返回单个返回值。当执行失败时,如果没有重写fallback,
Future.get()抛出异常。

3、observe()

事件注册前执行run()/construct(),支持接收多个值对象,取决于发射源。调用observe()
会返回一个hotObservable,也就是说,调用observe()自动触发执行run()/construct(),
无论是否存在订阅者。

如果继承的是HystrixCommand,hystrix会从线程池中取一个线程以非阻塞方式执行
run();如果继承的是HystrixObservableCommand,将以调用线程阻塞执construct()。

observe()使用方法:
调用observe()会返回一个Observable对象
调用这个Observable对象的subscribe()方法完成事件注册,从而获取结果

4、toObservable()

事件注册后执行run()/construct(),支持接收多个值对象,取决于发射源。调用
toObservable()会返回一个cold Observable,也就是说,调用toObservable()不会立即
触发执行run()/construct(),必须有订阅者订阅Observable时才会执行。

如果继承的是HystrixCommand,hystrix会从线程池中取一个线程以非阻塞方式执行
run(),调用线程不必等待run();如果继承的是HystrixObservableCommand,将以调用
线程堵塞执行construct(),调用线程需等待construct()执行完才能继续往下走。

toObservable()使用方法:
调用observe()会返回一个Observable对象
调用这个Observable对象的subscribe()方法完成事件注册,从而获取结果
需注意的是,HystrixCommand也支持toObservable()和observe(),但是即使将
HystrixCommand转换成Observable,它也只能发射一个值对象。只有
HystrixObservableCommand才支持发射多个值对象。

7、几种执行方法之间的关系

Hystrix原理及熔断降级理解 - 图2
execute()实际是调用了queue().get()
queue()实际调用了toObservable().toBlocking().toFuture()
observe()实际调用toObservable()获得一个cold Observable,再创建一个ReplaySubject对象订阅Observable,将源 Observable转化为hot Observable。因此调用observe()会自动触发执行run()/construct()。
Hystrix总是以Observable的形式作为响应返回,不同执行命令的方法只是进行了相应的转换。

熔断

1、简介

现实生活中,可能大家都有注意到家庭电路中通常会安装一个保险盒,当负载过载时,保险盒中的保险丝会自动熔断,以保护电路及家里的各种电器,这就是熔断器的一个常见例子。Hystrix中的熔断器(Circuit Breaker)也是起类似作用,Hystrix在运行过程中会向每个commandKey对应的熔断器报告成功、失败、超时和拒绝的状态,熔断器维护并统计这些数据,并根据这些统计信息来决策熔断开关是否打开。如果打开,熔断后续请求,快速返回。隔一段时间(默认是5s)之后熔断器尝试半开,放入一部分流量请求进来,相当于对依赖服务进行一次健康检查,如果请求成功,熔断器关闭。

2、简单配置

Circuit Breaker主要包括如下6个参数:

  1. circuitBreaker.enabled — 是否启用熔断器,默认是TRUE。
  2. circuitBreaker.forceOpen — 熔断器强制打开,始终保持打开状态,不关注熔断开关的实际状态。默认值FLASE。
  3. circuitBreaker.forceClosed — 熔断器强制关闭,始终保持关闭状态,不关注熔断开关的实际状态。默认值FLASE。
  4. circuitBreaker.errorThresholdPercentage — 错误率,默认值50%,例如一段时间(10s)内有100个请求,其中有54个超时或者异常,那么这段时间内的错误率是54%,大于了默认值50%,这种情况下会触发熔断器打开。
  5. circuitBreaker.requestVolumeThreshold — 默认值20。含义是一段时间内至少有20个请求才进行errorThresholdPercentage计算。比如一段时间了有19个请求,且这些请求全部失败了,错误率是100%,但熔断器不会打开,总请求数不满足20。
  6. circuitBreaker.sleepWindowInMilliseconds — 半开状态试探睡眠时间,默认值5000ms。如:当熔断器开启5000ms之后,会尝试放过去一部分流量进行试探,确定依赖服务是否恢复。

3、工作原理

Hystrix原理及熔断降级理解 - 图3

第一步,调用allowRequest()判断是否允许将请求提交到线程池

如果熔断器强制打开,circuitBreaker.forceOpen为true,不允许放行,返回。
如果熔断器强制关闭,circuitBreaker.forceClosed为true,允许放行。此外不必关注熔断器实际状态,也就是说熔断器仍然会维护统计数据和开关状态,只是不生效而已。
第二步,调用isOpen()判断熔断器开关是否打开

如果熔断器开关打开,进入第三步,否则继续;
如果一个周期内总的请求数小于circuitBreaker.requestVolumeThreshold的值,允许请求放行,否则继续;
如果一个周期内错误率小于circuitBreaker.errorThresholdPercentage的值,允许请求放行。否则,打开熔断器开关,进入第三步。
第三步,调用allowSingleTest()判断是否允许单个请求通行,检查依赖服务是否恢复

如果熔断器打开,且距离熔断器打开的时间或上一次试探请求放行的时间超过circuitBreaker.sleepWindowInMilliseconds的值时,熔断器器进入半开状态,允许放行一个试探请求;否则,不允许放行。
此外,为了提供决策依据,每个熔断器默认维护了10个bucket,每秒一个bucket,当新的bucket被创建时,最旧的bucket会被抛弃。其中每个blucket维护了请求成功、失败、超时、拒绝的计数器,Hystrix负责收集并统计这些计数器。

4、熔断降级实现方法

  1. @RestController
  2. @RequestMapping("/book")
  3. @DefaultProperties(defaultFallback = "selBookFail")//指定默认的失败回调方法
  4. public class BookController {
  5. @Autowired
  6. private BookService bookService;
  7. @PostMapping("/add")
  8. public boolean addBook(@RequestBody Book book){
  9. return bookService.addBook(book);
  10. };
  11. @GetMapping("/get/{bookId}")
  12. @HystrixCommand(commandProperties =
  13. {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")})
  14. //一旦调用服务方法失败并抛出了错误信息后会自动调用指定方法
  15. public Book selOneBook(@PathVariable("bookId") Integer bookId){
  16. System.out.println("BookProviderController:"+bookId);
  17. Book book = bookService.selOneBook(bookId);
  18. if (book == null){
  19. throw new RuntimeException("没有此ID信息");
  20. }
  21. return book;
  22. };
  23. //自定义失败备用方法
  24. public Book selBookFail(@PathVariable("bookId") Integer bookId){
  25. System.out.println("selFailMethod:"+bookId);
  26. return new Book().setBookId(bookId).setBookName("此ID:"+bookId+"没有对应的信息,请检查");
  27. }
  28. @GetMapping("/list")
  29. @HystrixCommand(commandProperties =
  30. {@HystrixProperty(name = "execution.isolation.strategy",value = "THREAD")},threadPoolProperties = {
  31. @HystrixProperty(name = "coreSize",value = "3"),
  32. @HystrixProperty(name = "maxQueueSize",value = "5"),
  33. @HystrixProperty(name = "queueSizeRejectionThreshold",value = "5")})
  34. public List<Book> selAllBook(){
  35. return bookService.selAllBook();
  36. };
  37. @DeleteMapping("/del/{id}")
  38. @HystrixCommand
  39. public boolean delBook(@PathVariable("id") Integer bookId){
  40. return bookService.delBook(bookId);
  41. };
  42. @Autowired
  43. private DiscoveryClient client;
  44. @GetMapping("/discovery")
  45. public Object getDiscovery(){
  46. //获取服务列表清单
  47. List<String> clientServices = client.getServices();
  48. System.out.println(clientServices);
  49. //获取具体的一个微服务
  50. List<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER-BOOK-8001");
  51. for (ServiceInstance instance : instances) {
  52. System.out.println(instance.getServiceId()+instance.getPort()+instance.getUri()+instance.getHost());
  53. }
  54. return this.client;
  55. }
  56. }

② 客户端实现
③ 网关实现

5、隔离模式

Hystrix提供了两种隔离模式:线程池隔离模式、信号量隔离模式。

  • 线程池隔离模式:使用一个线程池来存储当前请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求先入线程池队列。这种方式要为每个依赖服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)

  • 信号量隔离模式:使用一个原子计数器(或信号量)记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃该类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)

    6、主次模式

    有时系统具有两种行为- 主要和次要,或主要和故障转移。主要和次要逻辑涉及到不同的网络调用和业务逻辑,所以需要将主次逻辑封装在不同的Command中,使用线程池进行隔离。为了实现主从逻辑切换,可以将主次command封装在外观HystrixCommand的run方法中,并结合配置中心设置的开关切换主从逻辑。由于主次逻辑都是经过线程池隔离的HystrixCommand,因此外观HystrixCommand可以使用信号量隔离,而没有必要使用线程池隔离引入不必要的开销。原理图如下:
    Hystrix原理及熔断降级理解 - 图4
    主次模型的使用场景还是很多的。如当系统升级新功能时,如果新版本的功能出现问题,通过开关控制降级调用旧版本的功能。示例代码如下:

    1. public class CommandFacadeWithPrimarySecondary extends HystrixCommand<String> {
    2. private final static DynamicBooleanProperty usePrimary = DynamicPropertyFactory.getInstance().getBooleanProperty("primarySecondary.usePrimary", true);
    3. private final int id;
    4. public CommandFacadeWithPrimarySecondary(int id) {
    5. super(Setter
    6. .withGroupKey(HystrixCommandGroupKey.Factory.asKey("SystemX"))
    7. .andCommandKey(HystrixCommandKey.Factory.asKey("PrimarySecondaryCommand"))
    8. .andCommandPropertiesDefaults(
    9. // 由于主次command已经使用线程池隔离,Facade Command使用信号量隔离即可
    10. HystrixCommandProperties.Setter()
    11. .withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)));
    12. this.id = id;
    13. }
    14. @Override
    15. protected String run() {
    16. if (usePrimary.get()) {
    17. return new PrimaryCommand(id).execute();
    18. } else {
    19. return new SecondaryCommand(id).execute();
    20. }
    21. }
    22. @Override
    23. protected String getFallback() {
    24. return "static-fallback-" + id;
    25. }
    26. @Override
    27. protected String getCacheKey() {
    28. return String.valueOf(id);
    29. }
    30. private static class PrimaryCommand extends HystrixCommand<String> {
    31. private final int id;
    32. private PrimaryCommand(int id) {
    33. super(Setter
    34. .withGroupKey(HystrixCommandGroupKey.Factory.asKey("SystemX"))
    35. .andCommandKey(HystrixCommandKey.Factory.asKey("PrimaryCommand"))
    36. .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("PrimaryCommand"))
    37. .andCommandPropertiesDefaults( HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(600)));
    38. this.id = id;
    39. }
    40. @Override
    41. protected String run() {
    42. return "responseFromPrimary-" + id;
    43. }
    44. }
    45. private static class SecondaryCommand extends HystrixCommand<String> {
    46. private final int id;
    47. private SecondaryCommand(int id) {
    48. super(Setter
    49. .withGroupKey(HystrixCommandGroupKey.Factory.asKey("SystemX"))
    50. .andCommandKey(HystrixCommandKey.Factory.asKey("SecondaryCommand"))
    51. .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("SecondaryCommand"))
    52. .andCommandPropertiesDefaults( HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100)));
    53. this.id = id;
    54. }
    55. @Override
    56. protected String run() {
    57. return "responseFromSecondary-" + id;
    58. }
    59. }
    60. public static class UnitTest {
    61. @Test
    62. public void testPrimary() {
    63. HystrixRequestContext context = HystrixRequestContext.initializeContext();
    64. try {
    65. ConfigurationManager.getConfigInstance().setProperty("primarySecondary.usePrimary", true);
    66. assertEquals("responseFromPrimary-20", new CommandFacadeWithPrimarySecondary(20).execute());
    67. } finally {
    68. context.shutdown();
    69. ConfigurationManager.getConfigInstance().clear();
    70. }
    71. }
    72. @Test
    73. public void testSecondary() {
    74. HystrixRequestContext context = HystrixRequestContext.initializeContext();
    75. try {
    76. ConfigurationManager.getConfigInstance().setProperty("primarySecondary.usePrimary", false);
    77. assertEquals("responseFromSecondary-20", new CommandFacadeWithPrimarySecondary(20).execute());
    78. } finally {
    79. context.shutdown();
    80. ConfigurationManager.getConfigInstance().clear();
    81. }
    82. }
    83. }
    84. }

    通常情况下,建议重写getFallBack或resumeWithFallback提供自己的备用逻辑,
    但不建议在回退逻辑中执行任何可能失败的操作

    7、@HystrixCommand注解属性

    1. @HystrixCommand(fallbackMethod = "xxx_method", // 指定降级方法
    2. groupKey = "strGroupCommand", // 分组的key
    3. commandKey = "strCommarld", // 命令分组的key
    4. threadPoolKey = "strThreadPool", // 线程池key值,相同key共用一个线程池;这三个key都是划分线程池相关
    5. commandProperties = {
    6. //设置隔离策略,THREAD 表示线程她SEMAPHORE:信号他隔离
    7. @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
    8. //当隔离策略选择信号他隔离的时候,用来设置信号地的大小(最大并发数)
    9. @HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),
    10. //配置命令执行的超时时间
    11. @HystrixProperty(name = "execution.isolation.thread.timeoutinMilliseconds", value = "10"),
    12. //是否启用超时时间
    13. @HystrixProperty(name = "execution.timeout.enabled", value = "true"),
    14. //执行超时的时候是否中断
    15. @HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),
    16. //执行被取消的时候是否中断
    17. @HystrixProperty(name = "execution.isolation.thread.interruptOnCancel", value = "true"),
    18. //允许回调方法执行的最大并发数
    19. @HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"),
    20. //服务降级是否启用,是否执行回调函数
    21. @HystrixProperty(name = "fallback.enabled", value = "true"),
    22. @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
    23. //该属性用来设置在滚动时间窗中,断路器熔断的最小请求数。例如,默认该值为20的时候,
    24. //如果滚动时间窗(默认10秒)内仅收到了19个请求,即使这19个请求都失败了, 断路器也不会打开。
    25. @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
    26. // 该属性用来设置在熔动时间窗中表示在滚动时间窗中,在请求数量超过
    27. // circuitBreaker.requestVolumeThreshold 的情况下,如果错误请求数的百分比超过50,
    28. //就把断路器设置为“打开”状态,否则就设置为“关闭”状态。
    29. @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
    30. // 该属性用来设置当断路器打开之后的休眠时间窗。休眠时间窗结束之后,
    31. //会将断路器置为"半开”状态,尝试熔断的请求命令,如果低然失败就将断路器继续设置为"打开”状态,
    32. //如果成功就设置为"关闭”状态。
    33. @HystrixProperty(name = "circuitBreaker.sleepWindowinMilliseconds", value = "5009"),
    34. //断路器强制打开
    35. @HystrixProperty(name = "circuitBreaker.force0pen", value = "false"),
    36. // 断路器强制关闭
    37. @HystrixProperty(name = "circuitBreaker.forceClosed", value = "false"),
    38. //滚动时间窗设置,该时间用于断路器判断健康度时需要收集信息的持续时间
    39. @HystrixProperty(name = "metrics.rollingStats.timeinMilliseconds", value = "10000"),
    40. //该属性用来设置滚动时间窗统计指标信息时划分”桶"的数量,断路器在收集指标信息的时候会根据设置的时间窗长度拆分成多个"相"来累计各度量值,每个”桶"记录了-段时间内的采集指标。
    41. //比如10秒内拆分成10个”桶"收集这样,所以timeinMilliseconds 必须能被numBuckets 整除。否则会抛异常
    42. @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
    43. //该属性用来设置对命令执行的延迟是否使用百分位数来跟踪和计算。如果设置为false,那么所有的概要统计都将返回-1.
    44. @HystrixProperty(name = "metrics .rollingPercentile.enabled", value = "false"),
    45. //该属性用来设置百分位统计的滚动窗口的持续时间, 单位为毫秒。
    46. @HystrixProperty(name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"),
    47. //该属性用来设置百分位统计演动窗口中使用“桶”的数量。
    48. @HystrixProperty(name = "metrics.rollingPercentile.numBuckets", value = "60000"),
    49. // 该属性用来设置在执行过程中每个 “桶”中保留的最大执行次数。如果在滚动时间窗内发生超过该设定值的执行次数,就从最初的位置开始重写。例如,将该值设置为100,燎动窗口为10秒, 若在10秒内一 一个“桶 ” 中发生7500次执行,
    50. //那么该“桶”中只保留最后的100次执行的统计。另外,增加该值的大小将会增加内存量的消耗, 并增加排序百分位数所需的计算
    51. @HystrixProperty(name = "metrics.rollingPercentile.bucketSize", value = "100"),
    52. //该属性用来设置采集影响断路器状态的健康快照(请求的成功、错误百分比) 的间隔等待时间。
    53. @HystrixProperty(name = "metrics.healthSnapshot.intervalinMilliseconds", value = "500"),
    54. //是否开启请求缓存
    55. @HystrixProperty(name = "requestCache.enabled", value = "true"),
    56. // HystrixCommand的执行和时间是否打印日志到HystrixRequestLog中
    57. @HystrixProperty(name = "requestLog.enabled", value = "true"),
    58. },
    59. threadPoolProperties = {
    60. //该参数用来设置执行命令线程他的核心线程数,该值 也就是命令执行的最大并发量
    61. @HystrixProperty(name = "coreSize", value = "10"),
    62. //该参数用来设置线程她的最大队列大小。当设置为-1时,线程池将使用SynchronousQueue 实现的队列,
    63. // 否则将使用LinkedBlocakingQueue实现队列
    64. @HystrixProperty(name = "maxQueueSize", value = "-1"),
    65. // 该参数用来为队列设置拒绝阀值。 通过该参数, 即使队列没有达到最大值也能拒绝请求。
    66. //該参数主要是対linkedBlockingQueue 队列的朴充,因为linkedBlockingQueue
    67. //队列不能动态修改它的对象大小,而通过该属性就可以调整拒绝请求的队列大小了。
    68. @HystrixProperty(name = "queueSizeRejectionThreshold", value = "5"),
    69. }
    70. )

    8、Hystrix参数配置

    hystrix.command.default和hystrix.threadpool.default中的default为默认CommandKey

    ①、Execution相关的属性的配置:

  1. hystrix.command.default.execution.isolation.strategy 隔离策略,默认是Thread, 可选Thread|Semaphore
  2. hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令执行超时时间,默认1000ms
  3. hystrix.command.default.execution.timeout.enabled 执行是否启用超时,默认启用true
  4. hystrix.command.default.execution.isolation.thread.interruptOnTimeout 发生超时是是否中断,默认true
  5. hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。
  6. 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相关的属性

  1. hystrix.command.default.circuitBreaker.enabled 用来跟踪circuit的健康性,如果未达标则让request短路。默认true
  2. hystrix.command.default.circuitBreaker.requestVolumeThreshold 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求,即使19个请求都失败,也不会触发circuit break。默认20
  3. hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds 触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒绝request,也就是5000毫秒后才会关闭circuit。默认5000
  4. hystrix.command.default.circuitBreaker.errorThresholdPercentage错误比率阀值,如果错误率>=该值,circuit会被打开,并短路所有请求触发fallback。默认50
  5. hystrix.command.default.circuitBreaker.forceOpen 强制打开熔断器,如果打开这个开关,那么拒绝所有request,默认false
  6. hystrix.command.default.circuitBreaker.forceClosed 强制关闭熔断器 如果这个开关打开,circuit将一直关闭且忽略circuitBreaker.errorThresholdPercentage

④、Metrics相关参数

  1. hystrix.command.default.metrics.rollingStats.timeInMilliseconds 设置统计的时间窗口值的,毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000
  2. hystrix.command.default.metrics.rollingStats.numBuckets 设置一个rolling window被划分的数量,若numBuckets=10,rolling window=10000,那么一个bucket的时间即1秒。必须符合rolling window % numberBuckets == 0。默认10
  3. hystrix.command.default.metrics.rollingPercentile.enabled 执行时是否enable指标的计算和跟踪,默认true
  4. hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds 设置rolling percentile window的时间,默认60000
  5. hystrix.command.default.metrics.rollingPercentile.numBuckets 设置rolling percentile window的numberBuckets。逻辑同上。默认6
  6. hystrix.command.default.metrics.rollingPercentile.bucketSize 如果bucket size=100,window=10s,若这10s里有500次执行,只有最后100次执行会被统计到bucket里去。增加该值会增加内存开销以及排序的开销。默认100
  7. hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds 记录health 快照(用来统计成功和错误绿)的间隔,默认500ms

⑤、Request Context 相关参数

  1. hystrix.command.default.requestCache.enabled 默认true,需要重载getCacheKey(),返回null时不缓存
  2. hystrix.command.default.requestLog.enabled 记录日志到HystrixRequestLog,默认true

⑥、Collapser Properties 相关参数

  1. hystrix.collapser.default.maxRequestsInBatch 单次批处理的最大请求数,达到该数量触发批处理,默认Integer.MAX_VALUE
  2. hystrix.collapser.default.timerDelayInMilliseconds 触发批处理的延迟,也可以为创建批处理的时间+该值,默认10
  3. hystrix.collapser.default.requestCache.enabled 是否对HystrixCollapser.execute() and HystrixCollapser.queue()的cache,默认true

⑦、ThreadPool 相关参数

线程数默认值10适用于大部分情况(有时可以设置得更小),如果需要设置得更大,那有个基本得公式可以follow:requests per second at peak when healthy × 99th percentile latency in seconds + some breathing room每秒最大支撑的请求数 (99%平均响应时间 + 缓存值)比如:每秒能处理1000个请求,99%的请求响应时间是60ms,那么公式是:(0.060+0.012)

基本的原则是保持线程池尽可能小,他主要是为了释放压力,防止资源被阻塞。 当一切都是正常的时候,线程池一般仅会有1到2个线程激活来提供服务

  1. hystrix.threadpool.default.coreSize 并发执行的最大线程数,默认10
  2. hystrix.threadpool.default.maxQueueSize BlockingQueue的最大队列数,当设为-1,会使用SynchronousQueue,值为正时使用LinkedBlcokingQueue。该设置只会在初始化时有效,之后不能修改threadpool的queue size,除非reinitialising thread executor。默认-1。
  3. hystrix.threadpool.default.queueSizeRejectionThreshold 即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝。因为maxQueueSize不能被动态修改,这个参数将允许我们动态设置该值。if maxQueueSize == -1,该字段将不起作用
  4. hystrix.threadpool.default.keepAliveTimeMinutes 如果corePoolSize和maxPoolSize设成一样(默认实现)该设置无效。如果通过plugin(https://github.com/Netflix/Hystrix/wiki/Plugins)使用自定义实现,该设置才有用,默认1.
  5. hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds 线程池统计指标的时间,默认10000
  6. hystrix.threadpool.default.metrics.rollingStats.numBuckets 将rolling window划分为n个buckets,默认10