运维知识
悠悠
2026年7月22日

Kafka 监控这块我踩了两年坑,今天把从 JMX 到 Grafana 的全套方案掏给你

我把这两年折腾 Kafka 监控的经验整理出来,从 JMX 指标怎么暴露、Exporter 怎么选、Prometheus 怎么抓、Grafana 面板怎么配,到告警规则怎么写,全流程给你讲清楚。看完你照着搭一套,基本能覆盖 90% 的 Kafka 线上问题。建议先收藏,搭的时候对着看。

先说清楚,Kafka 到底该监控啥

很多人一上来就问用啥工具,其实工具是最后一步。你得先知道 Kafka 出问题的时候,都是哪些指标先变脸。

我自己踩下来,最关键的就这么几类:

消费延迟(Consumer Lag),这是重中之重。Lag 就是消息生产了但还没被消费的数量。它一涨,要么是消费者处理不过来,要么是消费者挂了。我开头那次事故,就是 Lag 没监控。

Broker 的存活和吞吐。哪个 broker 挂了、每秒进出多少字节、请求处理耗时多少,这些直接反映集群健不健康。

Under Replicated Partitions(副本不同步分区数)。正常情况这个值应该是 0。一旦大于 0,说明有分区的副本没跟上,可能是某个 broker 压力大或者网络抖动,这是集群不稳的前兆。

Controller 数量。整个集群应该只有一个 Controller,如果监控显示 0 个或者 2 个,那你集群基本要出大事了,脑裂了。

磁盘、堆内存、GC。Kafka 是重度依赖磁盘和 PageCache 的,磁盘满了直接写不进去;堆内存和 GC 卡顿会让 broker 响应变慢。

先记住这几个,后面配面板和告警都围绕它们来。

JMX 是一切的源头

Kafka 是 Scala/Java 写的,它的内部指标全部通过 JMX(Java Management Extensions)暴露出来。你想拿到任何一个指标,本质上都是从 JMX 里读的。

默认情况下 Kafka 的 JMX 端口是不开的,你得手动开。在启动 Kafka 之前设置一个环境变量:

export JMX_PORT=9999

或者直接改 kafka-server-start.sh,在里面加上:

export KAFKA_JMX_OPTS="-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=你的服务器IP \
-Dcom.sun.management.jmxremote.port=9999 \
-Dcom.sun.management.jmxremote.rmi.port=9999"

这里有个坑我提醒一下,java.rmi.server.hostname 这个一定要写对,写成 127.0.0.1 或者不写,远程连 JMX 就会连不上,报一堆莫名其妙的 RMI 错误。我第一次搭的时候在这卡了俩小时,就是因为没配这个 hostname,本地能连远程死活连不上。

配好之后重启 Kafka,你可以用 jconsole 或者 jmxterm 连上去验证一下端口通不通。生产环境我一般会写个简单的检查:

echo "beans" | java -jar jmxterm.jar -l localhost:9999 -n | grep kafka

能看到一堆 kafka.server 开头的 bean,就说明 JMX 正常暴露了。

Exporter 怎么选,我给你说实话

JMX 数据 Prometheus 是直接读不了的,得有个中间转换的东西,这就是 Exporter。市面上主要有两条路:

第一条:JMX Exporter。这是官方 Prometheus 出的通用 JMX 转 Prometheus 工具。它有两种跑法,一种是作为 javaagent 挂在 Kafka 进程里跑,另一种是单独起个进程去连 JMX 端口。

我强烈推荐用 javaagent 模式,因为它性能好,直接在进程内读,不用走 RMI。配置方式是在 Kafka 启动参数里加:

export KAFKA_OPTS="-javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent.jar=7071:/opt/jmx_exporter/kafka.yml"

这里 7071 是暴露给 Prometheus 抓取的端口,kafka.yml 是配置文件,里面写你要转换哪些 JMX 指标。这个配置文件是个大工程,因为 JMX 的 bean 名字特别长特别乱,你得写正则把它们映射成规范的 Prometheus 指标名。

好消息是官方仓库里有现成的 kafka-2_0_0.yml 配置,直接拿来改改就能用,不用自己从头写。我贴一小段让你有个概念:

lowercaseOutputName: true
rules:
  - pattern: kafka.server<type=(.+), name=(.+)PerSec\w*><>Count
    name: kafka_server_$1_$2_total
    type: COUNTER
  - pattern: kafka.server<type=(.+), name=(.+), topic=(.+)><>Count
    name: kafka_server_$1_$2_total
    labels:
      topic: "$3"
    type: COUNTER

第二条:Kafka Exporter(danielqsj 那个)。这个专门针对 Kafka,最大的好处是它能直接算出 Consumer Lag,而且不依赖 JMX,它是通过 Kafka 协议直接连集群拉元数据的。

我的实战经验是:两个都上。JMX Exporter 负责 broker 的各种细粒度指标(GC、请求耗时、副本状态),Kafka Exporter 专门管消费延迟。两者互补,谁也替代不了谁。别偷懒只上一个。

Kafka Exporter 跑起来很简单:

./kafka_exporter --kafka.server=kafka1:9092 --kafka.server=kafka2:9092 --web.listen-address=:9308

它默认在 9308 端口暴露指标,其中最重要的就是 kafka_consumergroup_lag,这个指标带着 consumergrouptopicpartition 三个 label,粒度细到每个分区,特别好用。

Prometheus 把数据抓过来

Exporter 起好了,接下来让 Prometheus 定时去抓。改 prometheus.yml

scrape_configs:
  - job_name: 'kafka-broker'
    static_configs:
      - targets:
          - 'kafka1:7071'
          - 'kafka2:7071'
          - 'kafka3:7071'
        labels:
          cluster: 'prod-kafka'

  - job_name: 'kafka-exporter'
    static_configs:
      - targets: ['kafka-exporter-host:9308']
        labels:
          cluster: 'prod-kafka'

注意我这里给每个 job 打了个 cluster 的 label,这个习惯建议你养成。如果你公司有多套 Kafka 集群(生产、测试、大数据专用),后面在 Grafana 里就能用这个 label 做集群切换,不然指标全混一块儿你根本分不清哪个是哪个。

改完 reload 一下 Prometheus,去它的 Web UI 里 Status → Targets 看看,那几个 target 都是 UP 状态就成了。然后在查询框里敲个 kafka_consumergroup_lag,能出数据,说明整条链路通了。

Grafana 面板别自己从零画

到 Grafana 这步,很多人喜欢自己一个个 panel 拖,我劝你别。Grafana 官方 dashboard 市场里有大量现成的 Kafka 模板,直接导入 ID 就能用。

我常用的几个 ID 给你:

  • 7589:Kafka Exporter Overview,专看消费延迟的,简洁实用
  • 721:Kafka 集群整体监控,配合 JMX Exporter 用
  • 11962:比较全面的 Kafka 大盘

导入方式:Grafana 左边 Dashboard → Import → 填 ID → 选你的 Prometheus 数据源 → 完事。

导进来之后你八成会发现有些 panel 显示 No Data,这很正常,因为模板里的指标名和你 JMX Exporter 转出来的名字对不上。这时候别慌,点开那个 panel 编辑,看它的 PromQL 用的是啥指标,再去 Prometheus 里搜相近的名字替换掉就行。这个过程有点烦,但比你从零画快多了。

我自己最后是拿这几个模板拼了个组合大盘,把最关心的几块单独拎出来放在最顶上:Consumer Lag、Under Replicated Partitions、Active Controller Count、每个 broker 的 Bytes In/Out。一眼就能看出集群状态,不用往下翻。

告警规则,这才是能救命的部分

面板画得再漂亮,你也不可能 24 小时盯着屏幕。真正能让你少熬夜的是告警。我把这两年沉淀下来的核心告警规则给你,直接抄进 Prometheus 的 rules 文件里。

groups:
  - name: kafka-alerts
    rules:
      # 消费延迟过高
      - alert: KafkaConsumerLagHigh
        expr: sum(kafka_consumergroup_lag) by (consumergroup, topic) > 100000
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "消费组 {{ $labels.consumergroup }} 延迟过高"
          description: "topic {{ $labels.topic }} 积压已超过 10 万,当前 {{ $value }}"

      # 副本不同步
      - alert: KafkaUnderReplicatedPartitions
        expr: kafka_server_replicamanager_underreplicatedpartitions > 0
        for: 3m
        labels:
          severity: critical
        annotations:
          summary: "Broker {{ $labels.instance }} 存在副本不同步分区"

      # Controller 数量异常
      - alert: KafkaControllerCountAbnormal
        expr: sum(kafka_controller_kafkacontroller_activecontrollercount) != 1
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "集群 Controller 数量异常,当前 {{ $value }}"

      # Broker 掉线
      - alert: KafkaBrokerDown
        expr: up{job="kafka-broker"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Kafka Broker {{ $labels.instance }} 掉线"

这里有几个我踩过坑的点说一下。

Lag 告警的阈值别写死一个数拉倒。我一开始所有 topic 都用 10 万这个阈值,结果有个大流量 topic 平时 Lag 就在几万浮动,隔三差五误报,被半夜吵醒好几次。后来我针对不同 topic 分了级别,高吞吐的放宽,核心业务的收紧。你也可以用变化率来判断,比如 Lag 持续上涨且 5 分钟内涨了多少,这个比绝对值更能反映真实问题。

Controller 那条告警别偷懒不配。Controller 数量不等于 1,要么是没有(选主中,短暂正常),要么是脑裂(多个,灾难)。所以我给它 for: 1m,短暂的没有不告警,持续异常才报。

up == 0 这个 Broker 掉线告警看着简单,但它是最实在的兜底。哪怕别的都没配,这条你也得有。

一次真实的排查,告诉你监控上齐了有多爽

上个月又出了一次类似的事,但这次结局完全不一样。

那天下午三点多,钉钉群里 KafkaConsumerLagHigh 告警响了,说某个消费组 Lag 在涨。我打开 Grafana 大盘,Lag 曲线确实是一条往上的斜线,但涨得不算特别快。我第一时间看了 Under Replicated Partitions,是 0,Broker 全在线,Controller 也是 1 个,说明集群本身没问题,问题出在消费端。

然后我切到 Kafka Exporter 那个面板,按 partition 拆开看,发现只有几个特定分区的 Lag 在涨,其他分区正常。这就基本锁定了——不是消费者整体挂了,是消费能力分布不均,某几个分区的消费实例出问题了。

我去看对应消费实例的 JVM 监控(这个我们也接进了同一套 Prometheus),果然发现有个实例 Full GC 频率异常,堆内存快满了,处理速度掉下来了。重启那个实例,Lag 曲线十几分钟就降回去了。

整个过程从收到告警到定位根因,也就十来分钟,全程对着面板看,一条命令没敲。这跟我开头那次熬到四点的经历比,差距就是有没有一套能说话的监控。

几个千万别做的事

搭这套东西的时候,有几个坑我用血泪总结的,你千万别踩:

  • 别只监控 Broker 不监控 Consumer Lag。Broker 一切正常但消费积压,业务照样炸,Lag 才是业务最直接的感受。
  • 别把 JMX 端口对公网开着。JMX 默认不带认证,暴露公网等于把服务器门敞开了,一定要用防火墙锁死或者只在内网开。
  • 别所有 topic 用一个告警阈值,误报多了大家就麻木了,狼来了喊多了真出事没人理。
  • 别忘了监控 Exporter 本身。Exporter 挂了你的监控就瞎了,得给 Exporter 也配个 up 告警。
  • 别只看 Lag 绝对值忽略趋势,有时候 Lag 高但在稳定下降是正常追赶,误告警反而添乱。

最后唠两句

Kafka 监控这套东西,说复杂也不复杂,核心就是 JMX 出数据、Exporter 转格式、Prometheus 存和抓、Grafana 展示、Alertmanager 告警,这么一条链路。难点不在工具,在于你知不知道该盯哪些指标、阈值怎么定得既灵敏又不烦人。这些东西没有捷径,都是一次次事故堆出来的经验。

我自己的建议是,别等出了事故才想起来搭监控。你现在手头的 Kafka 集群,哪怕就先把 Consumer Lag 和 Broker 存活这两块监控上了,也比裸奔强一百倍。剩下的慢慢完善。

这套配置我整理成了完整的文件,包括 JMX Exporter 的 yml、Prometheus 的 scrape 和 rules、还有那几个 Grafana 大盘的 JSON。需要的话在公众号后台回复「kafka监控」,我打包发你,省得你自己一点点抠。

如果这篇对你有用,帮我点个赞、转发给身边还在裸奔跑 Kafka 的兄弟,也算是帮他少熬几个夜。下一期我打算讲讲 Kafka 消费积压后怎么快速追平以及分区扩容的那些坑,想看的评论区扣个 1。


公众号:耕云躬行录
个人博客:躬行笔记

文章目录

博主介绍

热爱技术的云计算运维工程师,Python全栈工程师,分享开发经验与生活感悟。
欢迎关注我的微信公众号@运维躬行录,领取海量学习资料

微信二维码