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

无需暴露Web端点获取Spring Boot Actuator指标数据的方法

问题:Spring Boot定时任务微服务不暴露Web端点获取内置指标

问题背景

基于Spring Boot 2.7.16开发仅运行定时任务的微服务,需要采集process.uptime这类内置指标,但出于安全考虑不想暴露Actuator的Web端点,也不想引入非必需的Spring Security依赖。原本暴露Web端点时,通过@Autowired MetricsEndpoint能正常获取指标,但关闭Web端点后,自定义MetricsEndpoint Bean(使用SimpleMeterRegistry)无法获取默认指标。

现有依赖配置

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.16</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
 </dependency>
 <dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <scope>runtime</scope>
 </dependency>

原可用代码(暴露Web端点时)

@Component
public class ScheduledTasks {

    private static final Logger LOGGER = LogManager.getLogger(ScheduledTasks.class.getName());

    @Autowired
    private MetricsEndpoint metrics;

    @Scheduled(fixedDelayString = "${schedule.checkAvailability}")
    public void checkUptime() {
        Set<String> listOfNames = metrics.listNames().getNames();
        LOGGER.info("Trying to log list of names");
        LOGGER.info(listOfNames);
        listOfNames.forEach(names -> {
            LOGGER.info(names);
        });
        // 获取JVM已运行时间(秒)
        Double uptimeInSeconds = metrics.metric("process.uptime", null).getMeasurements().get(0).getValue();
        LOGGER.info("uptimeInSeconds");
        LOGGER.info(uptimeInSeconds);
    }
}

ConfigMap配置

kind: ConfigMap
apiVersion: v1
metadata:
    name: example
data:
    management.endpoints.web.exposure.include: "health,info"
    management.endpoints.web.base-path: "/example/metrics/actuator"
    management.metrics.enable.all: "true"
    # 定时任务间隔(毫秒)
    schedule.checkAvailability: "60000"

失败的尝试

自定义MetricsEndpoint Bean,使用SimpleMeterRegistry,但日志显示可用指标名称为空,无法获取默认指标:

@Bean
public MetricsEndpoint metricsEndpoint() {
    SimpleMeterRegistry registery = new SimpleMeterRegistry();
    return new MetricsEndpoint(registery);
}

解决方法:通过JMX获取指标

在ConfigMap中添加spring.jmx.enabled: "true"(可自定义JMX域,具体可参考Spring官方JMX相关文档),然后通过JMX调用Metrics端点获取指标,实现代码如下:

private ArrayList<Map<String, Object>> getMetricMeasurements(String metric) throws Exception {
    Object individualMetric = null;
    Map<String, Object> metricMap = null;
    MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
    ObjectName metricsName = null;
    MBeanInfo mBeanInfo = null;
    ArrayList<Map<String, Object>> measurementList = null;

    try {
        LOGGER.info("looking at metricsObject");
        // 此处为默认Spring域或自定义域
        metricsName = new ObjectName("org.springframework.boot:type=Endpoint,name=Metrics");
        LOGGER.info(metricsName);
        LOGGER.info("looking at mBeanInfo");
        mBeanInfo = mBeanServer.getMBeanInfo(metricsName);
        LOGGER.info(mBeanInfo);

        if (mBeanInfo != null) {
            try {
                Object[] metricParam = { metric };
                String[] metricSignature = { String.class.getName(), List.class.getName() };
                LOGGER.info("looking at individualMetric");
                individualMetric = mBeanServer.invoke(metricsName, "metric", metricParam, metricSignature);
                LOGGER.info(individualMetric);
            } catch (Exception e) {
                LOGGER.error(e.getMessage());
            }
        }

        if (individualMetric != null) {
            ObjectMapper JSONMapper = new ObjectMapper();
            String jsonString = JSONMapper.writeValueAsString(individualMetric);
            LOGGER.info("metricMap");
            metricMap = JSONMapper.readValue(jsonString, Map.class);
            LOGGER.info(metricMap);
            LOGGER.info("measurementList");
            measurementList = (ArrayList<Map<String, Object>>) metricMap.get("measurements");
            LOGGER.info(measurementList);
        }
    } catch (Exception e) {
        LOGGER.error(e.getMessage());
    }

    return measurementList;
}

调用示例:getMetricMeasurements("process.uptime"),返回格式如下:

[{statistic=VALUE, value=具体数值}]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 13:38:12