3. 监控指标体系设计
在 Confluent Kafka 数据平台中,可观测性的第一道门槛不是“有没有监控”,而是“指标从哪里来、以什么粒度暴露、如何被统一采集”。Kafka 的指标来源天然分散:Broker 端通过 JMX 暴露大量 MBean,客户端(Producer/Consumer)通过 Metrics API 在进程内注册度量,而 Confluent 平台又提供了 Metrics Reporter 将服务端指标以更规整的方式推送出去。如果不对这三条来源做分层设计,最终会得到一堆命名混乱、粒度不一、无法关联的时序数据。本节的目标是建立一套“来源分层—对象分层—命名分层”的指标体系,覆盖 Broker、Topic、Partition、Consumer Group 四类核心对象。
三条指标来源的定位差异
JMX 是最底层的来源。Kafka Broker 启动后会在 JVM 内注册大量 MBean,例如 kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec、kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions、kafka.network:type=RequestMetrics,name=RequestsPerSec,request=Produce。JMX 的优点是覆盖最全、延迟最低,缺点是命名冗长、层级靠 ObjectName 表达,且需要 JMX 连接或 JMX Exporter 才能进入时序库。
Metrics API 面向客户端。Producer 和 Consumer 在应用进程内通过 MetricName 与 KafkaMetric 注册指标,例如 producer-metrics:record-send-rate、consumer-fetch-manager-metrics:records-lag-max。它的关键价值在于把“客户端视角”的延迟、重试、缓冲、拉取行为暴露出来,这是 Broker 端看不到的。使用方式通常是通过 metrics() 方法拿到 Map<MetricName, KafkaMetric>,再周期性导出。
Confluent Metrics Reporter 则是平台化的折中方案。它作为 Broker 的 metric.reporters 插件运行,把 Broker 指标按 Confluent 约定的命名推送到 HTTP 端点或下游系统,省去了逐个解析 MBean 的麻烦,同时保留了 Topic、Partition 级别的维度信息。三者不是替代关系,而是互补:JMX 保底、Metrics API 补客户端、Metrics Reporter 做平台统一出口。
分层命名:让指标可被检索和聚合
指标一旦进入时序库,命名就是检索契约。建议采用四段式:来源_对象_指标_维度。例如 Broker 级副本不足可命名为 kafka_broker_under_replicated_partitions,Partition 级滞后命名为 kafka_partition_log_end_offset{topic,partition},Consumer Group 级滞后命名为 kafka_consumergroup_lag{group,topic,partition}。维度标签只保留真正需要下钻的字段,避免高基数标签(如 client-id、instance-id)直接进入主指标,否则会拖垮存储。
这里有一个容易踩的坑:JMX 的 kafka.consumer:type=ConsumerFetcherManager,name=MaxLag,clientId=* 与 Metrics API 的 records-lag-max 表达的是同一件事,但一个在 Broker 侧、一个在客户端侧。分层设计时要明确“以哪一侧为准”。通常建议:Consumer Group 的滞后以客户端 Metrics API 为准,因为它反映真实消费进度;Broker 侧只保留 UnderReplicatedPartitions、IsrShrinksPerSec 这类集群健康指标。
采集参数与采样节奏
采样频率直接决定指标可用性。JMX Exporter 建议 15s 一次,与 Prometheus 默认 scrape_interval 对齐;客户端 Metrics API 导出周期建议 10s,因为客户端指标变化快,但过密会带来额外开销。Confluent Metrics Reporter 的推送间隔由 confluent.metrics.reporter.interval.ms 控制,默认 60000ms,生产环境可下调到 30000ms 以提升告警灵敏度。
# JMX Exporter 规则片段(示例)
rules:
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=MessagesInPerSec><>Count'
name: kafka_broker_messages_in_total
labels:
topic: "$1"
- pattern: 'kafka.server<type=ReplicaManager, name=UnderReplicatedPartitions><>Value'
name: kafka_broker_under_replicated_partitions
# Broker 端启用 Confluent Metrics Reporter(示例)
metric.reporters=io.confluent.metrics.reporter.ConfluentMetricsReporter
confluent.metrics.reporter.bootstrap.servers=localhost:9092
confluent.metrics.reporter.interval.ms=30000
四类对象的指标清单与判断依据
| 对象 | 核心指标 | 来源 | 异常判断参考 |
|---|---|---|---|
| Broker | UnderReplicatedPartitions、ActiveControllerCount、RequestHandlerAvgIdlePercent | JMX / Metrics Reporter | URP > 0 持续 5 分钟;空闲率 < 0.3 |
| Topic | MessagesInPerSec、BytesInPerSec、BytesOutPerSec | JMX / Metrics Reporter | 入流量骤降 50% 以上且非业务低峰 |
| Partition | LogEndOffset、LogSize、IsrShrinksPerSec、LeaderElectionRate | JMX | ISR 收缩频繁;Leader 切换次数上升 |
| Consumer Group | records-lag-max、records-consumed-rate、rebalance-rate | Metrics API | Lag 持续增长且消费速率下降;Rebalance 频繁 |
topic、partition、group 作为标签是必要的,但把 client-id、request-id 也作为标签会导致时序数量爆炸。建议在采集层做一次过滤或聚合,只保留排障时真正会下钻的维度。完成本节的分层设计后,你应当能够回答三个问题:每个指标来自哪条来源、它描述的是哪类对象、进入时序库后叫什么名字。这三件事确定下来,后续的告警规则、看板和容量分析才有稳定的数据基础。