无需暴露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
相关产品推荐
相关产品推荐

