健康、指标与追踪
节点通过 Spring Boot Actuator 的健康分组告诉平台是否该给它发流量、是否该重启它。有了 wow-opentelemetry,它还为工作的每个阶段记录一个 span,放在发起这项工作的请求、条目或消息的追踪中,并记录提交、订阅、定时器和查询的指标。本页说明两者,并列出应当对什么报警。
健康
类路径上有 Spring Boot Actuator 的健康支持时,宿主会提供节点的健康状况:
| 端点 | 报告 |
|---|---|
/actuator/health/readiness | 节点是否应当接收流量:Actuator 自己的就绪状态加上节点的 |
/actuator/health/liveness | 节点是否存活:Actuator 自己的存活状态加上节点的 |
/actuator/health/wow | 节点的每个组件,各为 UP、DEGRADED 或 DOWN |
组件:
| 组件 | 何时 DOWN(未就绪) | 何时 DEGRADED |
|---|---|---|
node | 节点没有在运行:启动中、排空中或已停止 | |
stores | 某个日志持续失败了 wow.health.stores.down-after(15 秒),期间没有成功过 | 某个日志在 wow.health.stores.window(1 分钟)内失败过 |
ownership | 它的租约存储不可用,或者在 wow.health.ownership.handover-grace(1 分钟)之后,节点仍没有拥有某个租约组中应得的任何分区 | 它在这么长时间内拥有的分区集合不是它应得的那份,或者租约存储最近失败过 |
topics | 它读取的另一个上下文的某个主题仍在加入中(除非 wow.health.topics.required: false) | |
subscriptions | 从不 | 某个订阅落后了 lag-degraded-at(10,000)个条目,或有 parked-degraded-at(100)个停放条目 |
executor | 执行器的在途量达到其上限的 saturation(90%) | |
liveness | 节点卡住了:在每个日志都有响应的情况下,它的调度器在 wow.health.liveness.stall-timeout(3 分钟)内没有运转,或者在途的命令没有完成。只有这一项会让存活探针失败 |
降级的组件不会改变分组的状态:它的作用是让人看到并据此报警。存活探针从不因存储故障而失败,节点排空期间也不会失败,所以一次故障不会让所有节点同时重启。探针不能等待的东西(日志的头部、订阅的落后量、停放的条目),节点每隔 wow.health.sample-interval(10 秒)采样一次,所以探针能立即得到回答。
响应除了状态之外还显示什么,由 Actuator 自己的设置决定(management.endpoint.health.show-details,默认 never)。详情包含计数、状态和异常类名,从不包含消息或地址。探针的写法见 Kubernetes。
指标与追踪
把 wow-opentelemetry 放到类路径上。span 通过应用的 OpenTelemetry Bean 输出,例如 Spring Boot 带 SDK 及其导出器的那个,否则使用全局的,例如 Java agent 的。指标输出到应用的 Micrometer MeterRegistry,例如带 Prometheus 或 OTLP registry 的 Actuator,否则使用 Micrometer 的全局 registry。wow.opentelemetry.enabled: false 同时关闭两者。
Span。 命令和订阅的每个阶段都是一个 span,位于它的请求、日志条目或 Kafka 消息所携带的追踪中:
| 阶段 | Span |
|---|---|
| 准入 | admit <context>.<aggregate>,一个 server span |
| 执行、决定、追加 | execute、decide、append <context>.<aggregate> |
| 订阅处理日志的一个条目 | handle <subscription> |
| 订阅处理主题的一条消息 | <topic> process,一个 consumer span |
| 定时器触发 | fire <command type> |
| 查询 | 每个查询一个 span |
| Kafka 发送 | 每次发送一个 producer span |
span 以属性的形式带着上下文、聚合、租户、命令和订阅(wow.context、wow.aggregate、wow.tenant.id、wow.command、wow.subscription 等),所以一条追踪可以跨服务跟随一条命令经过它的 Saga。
指标。 主要的指标,按上下文、聚合、订阅或分区打标签:
| 指标 | 类型 | 度量 |
|---|---|---|
wow.command.commit | Timer | 一条命令的执行,从接收到得出结果,按结果分 |
wow.command.refused | Counter | 在内核接收之前就结束的命令:拒绝、繁忙的车道或节点、不可用的存储 |
wow.subscription.lag | Timer | 从一次提交到订阅处理它 |
wow.subscription.backlog | Gauge | 分区中位于订阅位置之后的条目数 |
wow.subscription.progress | Gauge | 订阅的位置相对于日志头部的比例,0 到 1:重建的进度 |
wow.subscription.parked | Gauge | 订阅停放的聚合数 |
wow.subscription.paused | Gauge | 订阅因系统性故障暂停某个分区时为 1 |
wow.subscription.throttled | Gauge | 订阅因背压限流某个分区时为 1 |
wow.subscription.undecodable | Counter | 这个版本无法解码的主题消息 |
wow.timer.delay | Timer | 定时器在到期时间之后延迟多久触发 |
wow.query | Timer | 一个查询,从准入到结束 |
wow.query.limit | Gauge | 存储当前的并发查询上限 |
wow.kafka.offset.gaps | Counter | 另一个上下文主题上的偏移量缺口(Kafka) |
wow.opentelemetry.sample-interval(15 秒)是读取采样型 gauge(停放条目和订阅的位置)的频率。
应当对什么报警
| 信号 | 含义 | 查看 |
|---|---|---|
| 某个节点的就绪状态持续几分钟为 down | 某个存储不可用,或者某个节点失去了它的分区 | /actuator/health/wow |
wow.subscription.parked 大于 0 | 有聚合在等待修复和运维人员处理 | ops 服务与控制台 |
wow.subscription.paused 长时间为 1 | 下游的存储或服务不可用 | 订阅的日志、存储 |
wow.subscription.backlog 持续增长 | 某个订阅落后了 | 它的落后量、处理函数的延迟、节点的执行器 |
wow.timer.delay 持续增长 | 定时器触发得晚了 | 节点的负载、定时器的存储 |
wow.kafka.offset.gaps 大于 0 | 某个订阅跳过了数据,或停在已过保留期的数据上 | 主题的保留期 |
带 wow.command.busy 的 wow.command.refused | 节点在负载下拒绝命令 | 节点数、存储的延迟 |