1、动机
当HystrixCommand
和 HystrixObservableCommands
执行时,它们会生成执行结果和延迟的指标。这对系统的操作人员非常有用,因为他们可以深入了解系统是如何运行的。Hystrix 为每个命令键提供指标,并提供非常细的粒度(以秒为单位)。
这些指标在单独和总体上都是有用的。获取在请求中执行的命令集以及结果和延迟信息通常有助于调试。聚合度量在理解整体系统级行为方面很有用,并且适合发出警报或报告。Hystrix Dashboard
就是这样一个消费者。
下面是命令执行和编写度量的示例:
2、Hystrix 事件类型
Hystrix命令事件类型的完整集合在下表中指定。这些对应于 enum com.netflix.hystrix.HystrixEventType
。这些类型在 HystrixCommand
和 HystrixObservableCommands
之间共享。
在 HystrixCommand
中,只返回单个值,因此有1个用于执行的事件类型,如果需要,还有1个用于回退的事件类型。因此,成功意味着返回值和命令的完成。
在 HystrixObservableCommand
中,[0…n]的值可能会被返回,因此EMIT事件对应于返回的值,而其他执行事件对应于命令终止。如果您熟悉RxJava
, EMIT
等价于OnNext
, SUCCESS
等价于 OnCompleted
, FAILURE
等价于 OnError
。
命令执行事件类型(com.netflix.hystrix.HystrixEventType
)
命令 fallback 事件类型(com.netflix.hystrix.HystrixEventType
)
其他命令事件类型(com.netflix.hystrix.HystrixEventType
)
线程池事件类型(com.netflix.hystrix.HystrixEventType.ThreadPool
)
Collapser 事件类型(com.netflix.hystrix.HystrixEventType.Collapser
)
3、Metrics 存储
当生成指标时,它们需要存储一段时间,然后才会被推出到不同的系统中。另一种选择是总是直接在盒外播放参数,除非音量非常低,否则这种方法不太可能有很好的效果。相反,Hystrix选择的方法是将指标写入内存中的数据结构。这些存储指标允许在以后的某个点进行查询。
Hystrix 1.5.0 中存储指标的特定数据结构发生了变化。
3.1 版本 1.4.x
在Hystrix 1.4.x 版本中,度量是用来聚合数据结构的。HystrixRollingNumber
捕获事件的计数,HystrixRollingPercentile
捕获具有有趣分布的数量的观察结果。例如,使用 HystrixRollingPercentile
跟踪命令延迟和折叠器批大小。指标在命令执行时同步写入这些数据结构。这些数据结构支持滚动模型,其中只保存最近的指标。
3.2 HystrixRollingNumber
当命令开始执行时,这些数据结构将被初始化。HystrixRollingNumbers
需要两部分配置:桶的数量,以及要跟踪的指标的总体窗口。调用桶数n和整个窗口w(以毫秒为单位)。然后调用t (= w/n)桶的大小(以毫秒为单位)。考虑到配置,写操作总是进入最新的存储区,而读操作则与“热”存储区和之前的n-1个存储区相反。由于一次只需要n个桶,因此数据结构重用旧的桶以节省内存分配。因为所有的写操作都是同步的,所以没有后台工作来进行“桶滚动”。相反,每个 bucket 的一次不幸的写操作所付出的代价是更新指针并为写操作准备一个新的bucket。这个数据结构允许任何线程写入,因此内部同步逻辑允许安全写入,而不需要外部同步。
也请查看这些配置链接,以获得滚动号码如何进行记录的演示。
3.3 HystrixRollingPercentile
HystrixRollingPercentile
也类似。它共享了 HystrixRollingNumber
的桶语义,并具有一个桶中最大观测数的额外配置。对该数据结构的读取可以是分布的平均值或任意百分位数。在本例中,分布是在“hot”bucket和之前的n-1个bucket上计算的。
n和w的配置在“桶数配置”和“总体窗口配置”中公开。每个桶的最大计数在最大计数配置中暴露
4、读取 Metric
使用这些数据结构,可以直接请求聚合值。例如,您可以使用 HystrixRollingNumber
来查询滚动成功次数,或使用 HystrixRollingPercentile
来查询滚动平均数。例如,Hystrix断路器是基于成功与失败的滚动计数。hystrix-contrib
中的所有指标发布者和流都会读取这些滚动计数并自动发布聚合信息。
然而,故事变得更加复杂,任何层次的细节都超过了这一点。因为读取只返回这些聚合的值,所以我们没有能力进行任何面处理。例如,知道 FooCommand
在总体上失败了 50% 是很有趣的,但我还想知道它在墨西哥和巴西失败了 0%,在美国失败了 98%。当我们严格地进行聚合时,这种级别的细节就丢失了。
因此,在 Netflix 内部,我们已经开始解析 HystrixRequestLog
,然后使用它进行进一步的分析。HystrixRequestLog
跟踪请求中的所有事件,并将它们作为字符串提供。这不是最优的,但使一些事情成为可能。我们可以在每个 HTTP 请求结束时查看该值,然后在 HTTP 请求中推出该数据和所有其他上下文信息。这使得通过 HTTP 路径划分 Hystrix 结果/延迟成为可能,我们发现这很有价值。
4.1 版本 1.5.x 及以后
因此,我们重新设计了如何使用指标,以允许更多的灵活性。如果度量被建模为一级流,那么它们可以以任何任意的方式被使用。为此,我们为每个指标构建流。每个 HystrixCommandKey
和每个HystrixThreadPoolKey
都有一个可以订阅的启动事件和完成事件流。每个 HystrixCollapserKey
都有一个用于折叠操作的流。
为了保持向后兼容性(并验证这个抽象是否正确),hystrix-core
提供了所有可能针对HystrixRollingNumber/HystrixRollingPercentile
的聚合查询的实现,除了针对这些流进行计算之外。这有一些好处。我们不需要在Hystrix中维护复杂的代码,而是依赖于 RxJava 来实现线程安全的聚合操作。例如,按时间进行存储是使用 Observable.window 实现的。这是在后台线程上操作的,所以我们现在可以在后台线程上免费获得“bucket-rolling”行为,而不必自己实现它。
要创建这个抽象,每个命令不再发出命令范围的 HystrixRollingNumber
。相反,它会发出一个线程局部的rx.Subject。这样做是为了允许写操作在没有任何同步的情况下发生。从那里,每个事件被写入特定于命令、特定于线程池或特定于折叠器的rx.Subject。然后,这些主题在 Hystrix 公共API中被公开为可观察对象,如下所示:
Hystrix 用户可以创建任何最适合他们的领域的指标策略。提供了一些默认实现。例如RollingCommandEventCounterStream
。任何线程都可以同步地从这个流中读取最新的滚动值,该值在桶滚动时在后台被写入。
以下是提供的度量消费者,以及如何调用它们:
4.2 Bucketed Event 计数器
它们按类型计数事件。命令、线程池和折叠器都有不同的类型:HystrixEventType
, HystrixEventType.ThreadPool
和 HystrixEventType.Collapser
)
滚动计数器只考虑最后n个桶,就像上面的 HystrixRollingNumber/ Percentil
一样。累积计数器考虑自JVM启动以来的所有事件。
这些计数器可以通过调用 Observable<long[]> observe()
来作为流处理。这将在每次桶滚动时返回一个长数组。通过使用适当的事件类型枚举的序号作为长数组的索引,您可以找到任何事件类型的计数。
它们也可以同步读取。在这种情况下,可以保证读取最近计算的值。这并不包括当前正在写入的桶。在这种情况下,您可以为整个计数集合调用 long[] getLatest()
,或为特定的事件类型调用 long getLatest(HystrixEventType)
。
4.3 Bucketed Max-Concurrency 计数器
它们跟踪给定时间段内并发的最高级别标记。这只有一个滚动版本,因为累积计数器只能提供很少的信息。对命令和线程池进行跟踪。
这些计数器可以通过调用 Observable<Integer> observe()
来作为流处理。这将返回前n个观察桶中看到的最大并发数,并在每次桶滚动时发出。
它们也可以被同步读取,使用 int getLatest()
获取最近的计算值。
4.4 Bucketed 分布
它们跟踪一组观察结果,并允许通过滚动窗口对聚合分布进行查询。这将跟踪命令延迟、命令用户延迟和折叠器批大小。
这些计数器可以被当作一个流来处理,调用 Observable<CachedValuesHistogram> observe()
返回最新的聚合直方图,然后你可以进一步查询。
它们也可以同步读取,使用 CachedValuesHistogram getLatest
来读取最近的直方图,使用 int getLatestMean()
来读取最新的平均值,使用 int getLatestPercentile(long percentile)
来读取最近的百分位。
4.5 其他流
在这个领域,我们认为社区会有很多我们还没有想到的好点子。请让我们知道你是否在你的领域用特定的方式使用指标-我们很乐意听到你的经验。更棒的是,你可以自由提交你的作品作为示例或 hystrix-contrib
模块。
5、简单 streams
除了事件流之外,还有存在于任何给定事件之外的对理解系统很有用的度量。从1.5.0开始,所有这些都是新的
5.1 配置流
配置与任何命令或请求都有不同的生命周期。理解全局配置图通常很有用,所以1.5.0引入了一个专用的配置流(com.netflix.hystrix.config.HystrixConfigurationStream
)。该类知道如何查找所有当前配置值,然后将它们附加到计时器上,使其成为流
Hystrix 提供了一个将这些对象映射到JSON com.netflix.hystrix.contrib.sample.stream.HystrixConfigurationJsonStream
和一个嵌入流到一个在com.netflix.hystrix.contrib.sample.stream.HystrixConfigSseServlet
SSE servlet(在 hystrix-metrics-event-stream contrib
模块。您可以自由地使用这些模型来消费流,或者创建自己的模型。#1062和 #1063 提供了一些未来的方向,我们相信这些方向会更好,性能更好。
下面是 hystrix-examples-webapp 的SSE流输出:
data: {“type”:“HystrixConfig”,“commands”:{“CreditCardCommand”:{“threadPoolKey”:“CreditCard”,“groupKey”:“CreditCard”,“execution”:{“isolationStrategy”:“THREAD”,“threadPoolKeyOverride”:null,“requestCacheEnabled”:true,“requestLogEnabled”:true,“timeoutEnabled”:true,“fallbackEnabled”:true,“timeoutInMilliseconds”:3000,“semaphoreSize”:10,“fallbackSemaphoreSize”:10,“threadInterruptOnTimeout”:true},“metrics”:{“healthBucketSizeInMs”:500,“percentileBucketSizeInMilliseconds”:60000,“percentileBucketCount”:10,“percentileEnabled”:true,“counterBucketSizeInMilliseconds”:10000,“counterBucketCount”:10},“circuitBreaker”:{“enabled”:true,“isForcedOpen”:false,“isForcedClosed”:false,“requestVolumeThreshold”:20,“errorPercentageThreshold”:50,“sleepInMilliseconds”:5000}},“GetUserAccountCommand”:{“threadPoolKey”:“User”,“groupKey”:“User”,“execution”:{“isolationStrategy”:“THREAD”,“threadPoolKeyOverride”:null,“requestCacheEnabled”:true,“requestLogEnabled”:true,“timeoutEnabled”:true,“fallbackEnabled”:true,“timeoutInMilliseconds”:50,“semaphoreSize”:10,“fallbackSemaphoreSize”:10,“threadInterruptOnTimeout”:true},“metrics”:{“healthBucketSizeInMs”:500,“percentileBucketSizeInMilliseconds”:60000,“percentileBucketCount”:10,“percentileEnabled”:true,“counterBucketSizeInMilliseconds”:10000,“counterBucketCount”:10},“circuitBreaker”:{“enabled”:true,“isForcedOpen”:false,“isForcedClosed”:false,“requestVolumeThreshold”:20,“errorPercentageThreshold”:50,“sleepInMilliseconds”:5000}},“GetOrderCommand”:{“threadPoolKey”:“Order”,“groupKey”:“Order”,“execution”:{“isolationStrategy”:“THREAD”,“threadPoolKeyOverride”:null,“requestCacheEnabled”:true,“requestLogEnabled”:true,“timeoutEnabled”:true,“fallbackEnabled”:true,“timeoutInMilliseconds”:1000,“semaphoreSize”:10,“fallbackSemaphoreSize”:10,“threadInterruptOnTimeout”:true},“metrics”:{“healthBucketSizeInMs”:500,“percentileBucketSizeInMilliseconds”:60000,“percentileBucketCount”:10,“percentileEnabled”:true,“counterBucketSizeInMilliseconds”:10000,“counterBucketCount”:10},“circuitBreaker”:{“enabled”:true,“isForcedOpen”:false,“isForcedClosed”:false,“requestVolumeThreshold”:20,“errorPercentageThreshold”:50,“sleepInMilliseconds”:5000}},“GetPaymentInformationCommand”:{“threadPoolKey”:“PaymentInformation”,“groupKey”:“PaymentInformation”,“execution”:{“isolationStrategy”:“THREAD”,“threadPoolKeyOverride”:null,“requestCacheEnabled”:true,“requestLogEnabled”:true,“timeoutEnabled”:true,“fallbackEnabled”:true,“timeoutInMilliseconds”:1000,“semaphoreSize”:10,“fallbackSemaphoreSize”:10,“threadInterruptOnTimeout”:true},“metrics”:{“healthBucketSizeInMs”:500,“percentileBucketSizeInMilliseconds”:60000,“percentileBucketCount”:10,“percentileEnabled”:true,“counterBucketSizeInMilliseconds”:10000,“counterBucketCount”:10},“circuitBreaker”:{“enabled”:true,“isForcedOpen”:false,“isForcedClosed”:false,“requestVolumeThreshold”:20,“errorPercentageThreshold”:50,“sleepInMilliseconds”:5000}}},“threadpools”:{“User”:{“coreSize”:8,“maxQueueSize”:-1,“queueRejectionThreshold”:5,“keepAliveTimeInMinutes”:1,“counterBucketSizeInMilliseconds”:10000,“counterBucketCount”:10},“CreditCard”:{“coreSize”:8,“maxQueueSize”:-1,“queueRejectionThreshold”:5,“keepAliveTimeInMinutes”:1,“counterBucketSizeInMilliseconds”:10000,“counterBucketCount”:10},“Order”:{“coreSize”:8,“maxQueueSize”:-1,“queueRejectionThreshold”:5,“keepAliveTimeInMinutes”:1,“counterBucketSizeInMilliseconds”:10000,“counterBucketCount”:10},“PaymentInformation”:{“coreSize”:8,“maxQueueSize”:-1,“queueRejectionThreshold”:5,“keepAliveTimeInMinutes”:1,“counterBucketSizeInMilliseconds”:10000,“counterBucketCount”:10}},“collapsers”:{}}
5.2 利用流
同样,对共享资源(如信号量和线程池)的利用也很重要。1.5.0 引入了一个对利用率值进行采样的流。通过对这些值进行抽样,您可以深入了解利用率分布,这将有助于影响配置决策。我想最终将其视为反馈循环的一部分,它可以直接影响配置,但工作还没有开始。看到 #131
使用流在 com.netflix.hystrix.metric.sample.hystrixutilationstream
上建模。它在com.netflix.hystrix.contrib.sample.stream.hystrixutilationjsonstream
上映射为JSON,并嵌入到com.netflix.hystrix.contrib.sample.stream. hystrixutilationsseservlet
上的SSE servlet中。
下面是 hystrix-examples-webapp
的SSE流输出:
data: {“type”:“HystrixUtilization”,“commands”:{“CreditCardCommand”:{“activeCount”:0},“GetUserAccountCommand”:{“activeCount”:0},“GetOrderCommand”:{“activeCount”:1},“GetPaymentInformationCommand”:{“activeCount”:0}},“threadpools”:{“User”:{“activeCount”:0,“queueSize”:0,“corePoolSize”:8,“poolSize”:2},“CreditCard”:{“activeCount”:0,“queueSize”:0,“corePoolSize”:8,“poolSize”:1},“Order”:{“activeCount”:1,“queueSize”:0,“corePoolSize”:8,“poolSize”:2},“PaymentInformation”:{“activeCount”:0,“queueSize”:0,“corePoolSize”:8,“poolSize”:2}}}
5.3 请求流
为请求确定命令的范围对于分析目的通常是有用的。它允许其他请求级别的数据与 Hystrix 数据关联并一起分析。在 1.5.0 中,添加了一个专用的请求流。这在本质上与在每个请求的末尾检查 HystrixRequestLog
生成的字符串的想法相似,但是直接建模,而不是依赖于字符串解析。
这个流由 com.netflix.hystrix.metrics.HystrixRequestEventsStream
生成。它在com.netflix.hystrix.contrib.requests.stream.HystrixRequestEventsJsonStream
上有一个到JSON的转换,在SSE servlet中有一个嵌入:
以下是 hystrix-examples-webapp
的输出示例:
data: {“name”:“GetOrderCommand”,“events”:[“SUCCESS”],“latencies”:[111]},{“name”:“GetPaymentInformationCommand”,“events”:[“SUCCESS”],“latencies”:[15]},{“name”:“GetUserAccountCommand”,“events”:[“TIMEOUT”,“FALLBACK_SUCCESS”],“latencies”:[59],“cached”:2},{“name”:“CreditCardCommand”,“events”:[“SUCCESS”],“latencies”:[957]}],[{“name”:“GetUserAccountCommand”,“events”:[“SUCCESS”],“latencies”:[3],“cached”:2},{“name”:“GetOrderCommand”,“events”:[“SUCCESS”],“latencies”:[77]},{“name”:“GetPaymentInformationCommand”,“events”:[“SUCCESS”],“latencies”:[21]},{“name”:“CreditCardCommand”,“events”:[“SUCCESS”],“latencies”:[1199]}
6、Metrics Event Stream
您可以使用 hystrix-metrics-event-stream来启动 仪表板、实时警报和其他此类用例。
7、Metrics Publisher
您可以通过使用 HystrixMetricsPublisher 的实现来发布指标。
通过调用 HystrixPlugins.registerMetricsPublisher(HystrixMetricsPublisher 的实现)
.注册你的 HystrixMetricsPublisher
实现。
Hystrix 包括以下实现 Hystrix -contrib
模块:
- Netflix Servo: hystrix-servo-metrics-publisher
- Yammer Metrics: hystrix-yammer-metrics-publisher
以下部分解释了这些实现发布的指标:
7.1 命令指标
每个 HystrixCommand
都发布带有以下标签的度量:
- Servo 标签:
“instance”
,值:HystrixCommandKey.name()
- Servo 标签:
“type”
,值:“HystrixCommand”
7.2 信息和状态
- Boolean
isCircuitBreakerOpen
- Number
errorPercentage
- Number
executionSemaphorePermitsInUse
- String
commandGroup
- Number
currentTime
7.3 累积和滚动事件计数
累积计数(Counter)表示自应用程序启动以来的事件数量。
滚动计数(Gauge)由 metrics.rollingStats.* properties。它们是“时间点”计数,表示最近的x秒(例如10秒)。
7.4 延迟百分比:HystrixCommand.run()执行(Gauge)
这些指标表示 HystrixCommand.run()
方法(如果使用线程隔离,则在子线程上)执行时间的百分位数。
这些是 metrics.rollingPercentile.* properties. 配置的属性。
- Number
latencyExecute_mean
- Number
latencyExecute_percentile_5
- Number
latencyExecute_percentile_25
- Number
latencyExecute_percentile_50
- Number
latencyExecute_percentile_75
- Number
latencyExecute_percentile_90
- Number
latencyExecute_percentile_99
- Number
latencyExecute_percentile_995
7.5 延迟百分比:端到端执行(度量)
这些指标表示 HystrixCommand.execute()
或 HystrixCommand.queue()
的端到端执行时间的百分位数,直到返回响应(或在 queue()
的情况下准备返回)。
将其与 latencyExecute*
百分位数进行比较的目的是衡量线程排队/调度/执行、信号量、断路器逻辑和其他开销方面(包括度量捕获本身)的成本。
这些是 metrics.rollingPercentile.* properties. 配置的属性。
- Number
latencyTotal_mean
- Number
latencyTotal_percentile_5
- Number
latencyTotal_percentile_25
- Number
latencyTotal_percentile_50
- Number
latencyTotal_percentile_75
- Number
latencyTotal_percentile_90
- Number
latencyTotal_percentile_99
- Number
latencyTotal_percentile_995
7.6 属性值(信息)
这些信息度量报告 HystrixCommand
使用的实际属性值。这使您能够看到动态属性何时生效,并确认是否按预期设置了属性。
- Number
propertyValue_rollingStatisticalWindowInMilliseconds
- Number
propertyValue_circuitBreakerRequestVolumeThreshold
- Number
propertyValue_circuitBreakerSleepWindowInMilliseconds
- Number
propertyValue_circuitBreakerErrorThresholdPercentage
- Boolean
propertyValue_circuitBreakerForceOpen
- Boolean
propertyValue_circuitBreakerForceClosed
- Number
propertyValue_executionIsolationThreadTimeoutInMilliseconds
- String
propertyValue_executionIsolationStrategy
- Boolean
propertyValue_metricsRollingPercentileEnabled
- Boolean
propertyValue_requestCacheEnabled
- Boolean
propertyValue_requestLogEnabled
- Number
propertyValue_executionIsolationSemaphoreMaxConcurrentRequests
- Number
propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests
8 ThreadPool 指标
每个 HystrixThreadPool
都发布带有以下标签的指标:
- Servo 标签 :“instance”,值:
HystrixThreadPoolKey.name()
- Servo 标签 :“type”,值:
“HystrixThreadPool”
8.1 信息和状态
- String
name
- Number
currentTime
8.2 滚动计数(计)
- Number
rollingMaxActiveThreads
- Number
rollingCountThreadsExecuted
8.3 累积计数(Counter)
- Long
countThreadsExecuted
8.4 线程池状态 (Gauge)
- Number
threadActiveCount
- Number
completedTaskCount
- Number
largestPoolSize
- Number
totalTaskCount
- Number
queueSize
8.5 属性值(Informational)
- Number
propertyValue_corePoolSize
- Number
propertyValue_keepAliveTimeInMinutes
- Number
propertyValue_queueSizeRejectionThreshold
- Number
propertyValue_maxQueueSize
原文地址: