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

Micrometer自定义指标在Docker容器中多数返回0问题求助

自定义Prometheus指标在Docker容器中异常问题排查与解决

我需要在Spring Boot应用中添加自定义指标,并暴露在/actuator/prometheus路径下。本地调试时指标显示正常,但部署到Docker容器后,自定义指标my_load的结果大多为0.0,多次重启容器偶尔能得到非0值。怀疑是初始化阶段存在竞态条件,按照建议将OperatingSystemMXBean改为类成员后,容器内运行可稳定获取非0指标值。

原实现代码

@SpringBootApplication
public class CustomMetricsApplication {

    public static void main(String[] args) {
        SpringApplication.run(CustomMetricsApplication.class, args);
    }

    @RestController
    static class MyController {

        @GetMapping("/metrics")
        public List<Double> getMetrics() {
            List<Double> result = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                result.add(Math.random() * 100);
            }
            return result;
        }
    }
}

@Configuration
public class MetricsConfig {

    @Bean
    MeterBinder getLoadMeter() {
        return new LoadMetric();
    }
}

public class LoadMetric implements MeterBinder {

    private static final Logger logger = LoggerFactory.getLogger(LoadMetric.class);

    @Override
    public void bindTo(MeterRegistry meterRegistry) {
        Tags tags = Tags.of("application", "panda");
        meterRegistry.gauge("my_load", tags, this, LoadMetric::calculateMetricValue);
    }

    private double calculateMetricValue() {
        OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
        double metricValue = osBean.getProcessCpuLoad() * 100.0;
        logger.info("Value {}", metricValue);
        return metricValue;
    }
}

Dockerfile配置

FROM eclipse-temurin:17.0.7_7-jre-alpine

RUN mkdir -p /services/

COPY target/custom-metrics-1.0.0.jar /services

CMD java -XX:MinRAMPercentage=40.0 -XX:MaxRAMPercentage=80.0 -XX:+HeapDumpOnOutOfMemoryError   -jar /services/custom-metrics-1.0.0.jar

修改后运行日志

2023-06-13T06:33:31.370Z  INFO 1 --- [nio-8080-exec-1] c.happypanda.custommetrics.LoadMetric    : Value 0.0
2023-06-13T06:33:32.683Z  INFO 1 --- [nio-8080-exec-3] c.happypanda.custommetrics.LoadMetric    : Value 3.2380952380952377
2023-06-13T06:33:36.347Z  INFO 1 --- [nio-8080-exec-4] c.happypanda.custommetrics.LoadMetric    : Value 0.25
2023-06-13T06:33:38.673Z  INFO 1 --- [nio-8080-exec-5] c.happypanda.custommetrics.LoadMetric    : Value 0.07171029042667623
2023-06-13T06:33:41.188Z  INFO 1 --- [nio-8080-exec-6] c.happypanda.custommetrics.LoadMetric    : Value 0.09953550099535502
2023-06-13T06:33:43.564Z  INFO 1 --- [nio-8080-exec-7] c.happypanda.custommetrics.LoadMetric    : Value 0.14020329477742727
2023-06-13T06:33:48.971Z  INFO 1 --- [nio-8080-exec-8] c.happypanda.custommetrics.LoadMetric    : Value 0.046289152908501774
2023-06-13T06:34:04.070Z  INFO 1 --- [nio-8080-exec-9] c.happypanda.custommetrics.LoadMetric    : Value 0.022086025067638453
2023-06-13T06:34:05.289Z  INFO 1 --- [io-8080-exec-10] c.happypanda.custommetrics.LoadMetric    : Value 0.06839945280437756
2023-06-13T06:34:08.793Z  INFO 1 --- [nio-8080-exec-2] c.happypanda.custommetrics.LoadMetric    : Value 0.07137758743754462
2023-06-13T06:34:11.564Z  INFO 1 --- [nio-8080-exec-1] c.happypanda.custommetrics.LoadMetric    : Value 0.060168471720818295
2023-06-13T06:34:16.481Z  INFO 1 --- [nio-8080-exec-3] c.happypanda.custommetrics.LoadMetric    : Value 0.05089058524173028
2023-06-13T06:34:17.761Z  INFO 1 --- [nio-8080-exec-4] c.happypanda.custommetrics.LoadMetric    : Value 0.13063357282821686
2023-06-13T06:34:19.803Z  INFO 1 --- [nio-8080-exec-5] c.happypanda.custommetrics.LoadMetric    : Value 0.12239902080783352
2023-06-13T06:34:20.936Z  INFO 1 --- [nio-8080-exec-6] c.happypanda.custommetrics.LoadMetric    : Value 0.14705882352941177
2023-06-13T06:34:21.901Z  INFO 1 --- [nio-8080-exec-7] c.happypanda.custommetrics.LoadMetric    : Value 0.17286084701815038
2023-06-13T06:40:00.641Z  INFO 1 --- [io-8080-exec-10] c.happypanda.custommetrics.LoadMetric    : Value 0.011319510406567285

问题原因与解决方案

  • 问题原因:原代码中每次计算指标时都通过ManagementFactory.getPlatformMXBean()获取新的OperatingSystemMXBean实例,在Docker容器环境下,JVM初始化阶段的资源竞争可能导致获取的Bean无法正确采集CPU负载数据,返回0.0。
  • 解决方案:将OperatingSystemMXBean改为类成员变量,在类初始化时就获取实例并复用,避免重复获取带来的竞态问题,确保指标采集稳定。

修改后的LoadMetric代码如下:

public class LoadMetric implements MeterBinder {

    private static final Logger logger = LoggerFactory.getLogger(LoadMetric.class);
    // 改为类成员,初始化时获取实例
    private final OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);

    @Override
    public void bindTo(MeterRegistry meterRegistry) {
        Tags tags = Tags.of("application", "panda");
        meterRegistry.gauge("my_load", tags, this, LoadMetric::calculateMetricValue);
    }

    private double calculateMetricValue() {
        double metricValue = osBean.getProcessCpuLoad() * 100.0;
        logger.info("Value {}", metricValue);
        return metricValue;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 18:44:58