You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Kafka Prometheus消费lag指标显示0或NaN异常排查

环境信息
  • Spring Boot:2.3.5
  • spring-cloud-stream kafka-streams binder:Hoxton.SR8
  • 监控组件:spring-boot-starter-actuator,通过/prometheus端点暴露Kafka客户端原生监控指标
  • 手动升级后micrometer版本:1.7.5
异常表现

Kafka消费滞后(lag)相关指标kafka_consumer_fetch_manager_records_lag、kafka_consumer_fetch_manager_records_lag_max取值完全不符合预期:

  • 绝大多数场景下指标值固定为0或NaN,和kafka-console-consumer脚本查询到的真实非零lag值不符
  • 部分场景下指标值远高于实际真实lag值
    异常指标样例:
kafka_consumer_fetch_manager_records_lag{appName="EventValidator.local.2",client_id="EventValidator.local.2-StreamThread-1-consumer",env="local",instanceId="2",kafka_version="2.5.1",partition="0",spring_id="streams.0",topic="event-store",} 0.0

kafka_consumer_fetch_manager_records_lag_max{appName="EventValidator.local.2",client_id="EventValidator.local.2-StreamThread-1-consumer",env="local",instanceId="2",kafka_version="2.5.1",partition="0",spring_id="streams.0",topic="event-store",} 0.0
根因分析

该异常是三层逻辑不兼容共同导致的:

  1. Kafka Streams运行时除了执行业务消费的StreamThread线程对应的消费者客户端,还会创建状态恢复消费者(restore consumer)、全局状态存储消费者等内部客户端,这类客户端不会消费业务topic分区,本身lag值恒为0。Hoxton.SR8版本的binder没有做客户端过滤,把内部客户端的lag指标也一并暴露,大量0值指标和业务真实指标混在一起。
  2. 1.5.x~1.7.x版本的micrometer采集Kafka客户端MBean指标时,没有正确处理分区重平衡阶段的临时状态,会把分区未完成赋值阶段的0值缓存住,后续不会及时更新为真实lag值;同时存在标签重复注册时旧指标值不清理的问题,会导致数值虚高。
  3. Hoxton.SR8版本binder默认会给Kafka MBean指标追加spring_id自定义标签,会导致同一个消费者客户端的指标被重复注册,进一步加剧数值不更新、虚高的问题。
解决方案

按改造成本从低到高排序:

方案1:配置过滤+自定义采集规则(无需升级依赖,适合生产环境锁版本场景)

首先修改application配置,关闭默认的全量Kafka消费者指标采集,移除重复标签:

management:
  metrics:
    enable:
      kafka.consumer.fetch-manager: false
    tags:
      spring_id: ""
  endpoints:
    web:
      exposure:
        include: prometheus

新增自定义指标绑定配置,只采集业务消费线程的指标,过滤内部消费者:

@Configuration
public class KafkaStreamMetricsConfig {
    @Bean
    public MeterBinder kafkaStreamsConsumerMetricsBinder() {
        return registry -> {
            MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
            Set<ObjectName> consumerMBeans = platformMBeanServer.queryNames(new ObjectName("kafka.consumer:type=consumer-fetch-manager-metrics,client-id=*"), null);
            for (ObjectName mbean : consumerMBeans) {
                String clientId = mbean.getKeyProperty("client-id");
                if (clientId.contains("StreamThread") && !clientId.contains("restore") && !clientId.contains("global")) {
                    new KafkaClientMetrics((KafkaClient) MBeanServerInvocationHandler.newProxyInstance(
                            platformMBeanServer, mbean, KafkaClient.class, false
                    )).bindTo(registry);
                }
            }
        };
    }
}

注意:配置生效后会自动清理之前注册的无效0值指标,采集到的lag值和实际值偏差在1个poll周期内

方案2:升级兼容版本修复已知bug

在不升级Spring Boot 2.3.x主版本的前提下,升级存在bug的依赖到修复版本:

  • 将micrometer-core、micrometer-registry-prometheus升级到1.8.8及以上(1.8.x分支为Spring Boot 2.3.x兼容分支,修复了Kafka指标缓存不更新、NaN值处理错误、重复标签注册的问题)
  • 将spring-cloud-stream kafka-streams binder升级到Hoxton.SR12(Hoxton分支最终稳定版,修复了内部客户端指标无差别暴露、自定义标签重复追加的问题)
    升级后无需额外自定义配置,默认即可采集到正确的lag指标。

方案3:替换lag采集方式(最高准确率,无客户端兼容问题)

如果不想处理客户端和监控组件的兼容问题,可以直接放弃客户端本地上报的lag指标,采用更准确的采集方式:

  • 部署kafka-lag-exporter组件,通过Kafka AdminClient周期性拉取所有消费组的已提交offset、对应分区的最新offset,差值计算得到真实lag,该方式和kafka-console-consumer查询的数值完全一致,不受客户端版本、重平衡、内部组件的影响
  • 直接采集Kafka Broker端内置的消费组lag指标,不依赖客户端上报

内容的提问来源于stack exchange,提问作者Shades88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 01:27:28