# 107. hystrix 的 metric 统计相关的各种高阶配置讲解

metric:度量标准

# 为什么需要监控与报警?

HystrixCommand 执行的时候,会生成一些执行耗时等方面的统计信息。 这些信息对于系统的运维来说,是很有帮助的,因为我们通过这些统计信息可以看到整个系统是怎么运行的。 hystrix 对每个 command key 都会提供一份 metric,而且是秒级统计粒度的。

这些统计信息,无论是单独看,还是聚合起来看,都是很有用的。 如果将一个请求中的多个 command 的统计信息拿出来单独查看,包括耗时的统计,对 debug 系统是很有帮助的。 聚合起来的 metric 对于系统层面的行为来说,是很有帮助的,很适合做报警或者报表。 hystrix dashboard 就很适合。

# hystrix 的事件类型

官网直达 (opens new window) 很详细的 metric 讲解,还有他的流使用示例

对于 hystrix command 来说只会返回一个值,execute 只有一个 event type,fallback 也只有一个event type,那么返回一个 SUCCESS 就代表着命令执行的结束

对于 hystrix observable command 来说,多个值可能被返回,所以:

  • emit event 代表一个 value 被返回
  • success 代表成功
  • failure 代表异常

# execute event type

  • EMIT observable command 返回一个 value
  • SUCCESS 完成执行,并且没有报错
  • FAILURE 执行时抛出了一个异常,会触发 fallback
  • TIMEOUT 开始执行了,但是在指定时间内没有完成执行,会触发 fallback
  • BAD_REQUEST 执行的时候抛出了一个 HystrixBadRequestException
  • SHORT_CIRCUITED 短路器打开了,触发 fallback
  • THREAD_POOL_REJECTED 线程池的容量满了,被 reject,触发 fallback
  • SEMAPHORE_REJECTED 信号量的容量满了,被 reject,触发 fallback

# fallback event type

  • FALLBACK_EMIT observable command,fallback value 被返回了
  • FALLBACK_SUCCESS fallback 逻辑执行没有报错
  • FALLBACK_FAILURE fallback 逻辑抛出了异常,会报错
  • FALLBACK_REJECTION fallback 的信号量容量满了,fallback 不执行,报错
  • FALLBACK_MISSING fallback 没有实现,会报错

# 其他的 event type

  • EXCEPTION_THROWN command 生命自周期是否抛出了异常
  • RESPONSE_FROM_CACHE command 是否在 cache 中查找到了结果
  • COLLAPSED command 是否是一个合并 batch 中的一个

# thread pool event type

  • EXECUTED 线程池有空间,允许 command 去执行了
  • REJECTED 线程池没有空间,不允许 command 执行,reject 掉了

# collapser event type

  • BATCH_EXECUTED collapser 合并了一个 batch,并且执行了其中的 command
  • ADDED_TO_BATCH command 加入了一个 collapser batch
  • RESPONSE_FROM_CACHE 没有加入 batch,而是直接取了 request cache 中的数据

# metric storage

metric 被生成之后,就会按照一段时间来存储,存储了一段时间的数据才会推送到其他系统中, 比如 hystrix dashboard;另外一种方式,就是每次生成 metric 就实时推送 metric 流到其他地方, 但是这样的话,会给系统带来很大的压力

hystrix 的方式是将 metric 写入一个内存中的数据结构中,在一段时间之后就可以查询到; hystrix 1.5x 之后,采取的是为每个 command key 都生成一个 start event 和 completion event 流, 而且可以订阅这个流。每个 thread pool key 也是一样的,包括每个 collapser key 也是一样的。

每个 command 的 event 是发送给一个线程安全的 RxJava 中的 rx.Subject,因为是线程安全的,所以不需要进行线程同步

因此每个 command 级别的,threadpool 级别的,每个 collapser 级别的,event 都会发送到对应的 RxJava的 rx.Subject 对象中。这些 rx.Subject 对象接着就会被暴露出 Observable 接口,可以被订阅。

# metric 统计相关的配置

官网直达 (opens new window)

# metrics.rollingStats.timeInMilliseconds

设置统计的 rolling window,单位是毫秒,hystrix 只会维持这段时间内的 metric 供短路器统计使用

这个属性是不允许热修改的,默认值是 10000,就是 10 秒钟

HystrixCommandProperties.Setter()
   .withMetricsRollingStatisticalWindowInMilliseconds(int value)
1
2

# metrics.rollingStats.numBuckets

该属性设置每个滑动窗口被拆分成多少个 bucket,而且滑动窗口对这个参数必须可以整除,同样不允许热修改

默认值是 10,也就是说,每秒钟是一个 bucket

随着时间的滚动,比如又过了一秒钟,那么最久的一秒钟的 bucket 就会被丢弃,然后新的一秒的 bucket 会被创建

HystrixCommandProperties.Setter()
   .withMetricsRollingStatisticalWindowBuckets(int value)
1
2

# metrics.rollingPercentile.enabled

控制是否追踪请求耗时,以及通过百分比方式来统计,默认是 true

HystrixCommandProperties.Setter()
   .withMetricsRollingPercentileEnabled(boolean value)
1
2

# metrics.rollingPercentile.timeInMilliseconds

设置 rolling window 被持久化保存的时间,这样才能计算一些请求耗时的百分比,默认是 60000 = 60s,不允许热修改

相当于是一个大的 rolling window,专门用于计算请求执行耗时的百分比

HystrixCommandProperties.Setter()
   .withMetricsRollingPercentileWindowInMilliseconds(int value)
1
2

# metrics.rollingPercentile.numBuckets

设置 rolling percentile window 被拆分成的 bucket 数量,上面那个参数除以这个参数必须能够整除,不允许热修改

默认值是 6,也就是每 10s 被拆分成一个 bucket

HystrixCommandProperties.Setter()
   .withMetricsRollingPercentileWindowBuckets(int value)
1
2

# metrics.rollingPercentile.bucketSize

设置每个 bucket 的请求执行次数被保存的最大数量,如果在一个 bucket 内,执行次数超过了这个值,那么就会重新覆盖从 bucket 的开始再写

举例来说,如果 bucket size 设置为 100,而且每个 bucket 代表一个 10 秒钟的窗口, 但是在这个 bucket 内发生了 500 次请求执行,那么这个 bucket 内仅仅会保留 100 次执行

如果调大这个参数,就会提升需要耗费的内存,来存储相关的统计值,不允许热修改

默认值是 100

HystrixCommandProperties.Setter()
   .withMetricsRollingPercentileBucketSize(int value)
1
2

# metrics.healthSnapshot.intervalInMilliseconds

控制成功和失败的百分比计算,与影响短路器之间的等待时间,默认值是 500 毫秒

HystrixCommandProperties.Setter()
   .withMetricsHealthSnapshotIntervalInMilliseconds(int value)
1
2

TIP

一般来说这些配置使用默认即可